Firemonkey hides overflow of round corners using the style guide

In firemonkey, I am trying to make progress using rectangles with round corners. The simplest case is a rectangle (progress indicator) and a second rectangle inside it (progress so far). A simple example is attached.

Progressbar with corners (paint): Progressbar with corners (paint)

I have tried the following things:

  • Let the second rectangle also have rounded corners. This does not work because these roundings will change if the second rectangle is very short or almost at the end.
  • Use cliche. It's almost the same as hiding overflow in html / css, but Delphi doesn't include rounded corners in this function.
  • TPath, . , . , , .

:

  • , . , , . : . , 0 . , ..

, , ?

(): Progressbar result

!

Jan

+4
5

,

. , html/css, Delphi .

, ; , . ( , ), Layout ClipChildren true, Width.

:

type

  TRoundProgressBar = class (TLayout)
  strict private
    FProgress: Single;
    FFill: TBrush;
    FStroke: TStrokeBrush;
    StrokeRect, FillRect: TRectangle;
    FillLayout: TLayout;
    procedure SetFill(const Value: TBrush);
    procedure SetStroke(const Value: TStrokeBrush);
    procedure FillChanged(Sender: TObject);
    procedure StrokeChanged(Sender: TObject);
    procedure SetProgress(Progress: Single);
    procedure UpdateWidths;
  protected
    procedure Resize; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Fill: TBrush read FFill write SetFill;
    property Stroke: TStrokeBrush read FStroke write SetStroke;
    property Progress: Single read FProgress write SetProgress;
  end;

implementation

constructor TRoundProgressBar.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FFill := TBrush.Create(TBrushKind.Solid, $FFE0E0E0);
  FFill.OnChanged := FillChanged;
  FStroke := TStrokeBrush.Create(TBrushKind.Solid, $FF000000);
  FStroke.OnChanged := StrokeChanged;

  FillLayout := TLayout.Create(self);
  FillLayout.Parent := self;
  FillLayout.Align := TAlignLayout.Left;
  FillLayout.ClipChildren := true;

  FillRect := TRectangle.Create(FillLayout);
  FillRect.Parent := FillLayout;
  FillRect.Align := TAlignLayout.Left;
  FillRect.XRadius := 15;
  FillRect.YRadius := 15;

  StrokeRect := TRectangle.Create(self);
  StrokeRect.Parent := self;
  StrokeRect.Align := TAlignLayout.Contents;
  StrokeRect.XRadius := 15;
  StrokeRect.YRadius := 15;
  StrokeRect.Fill.Kind := TBrushKind.None;
end;

destructor TRoundProgressBar.Destroy;
begin
  FFill.Free;
  FStroke.Free;
  inherited;
end;

procedure TRoundProgressBar.SetFill(const Value: TBrush);
begin
  FFill.Assign(Value);
end;

procedure TRoundProgressBar.SetProgress(Progress: Single);
begin
  FProgress := Min(Max(Progress, 0), 100);
  UpdateWidths;
end;

procedure TRoundProgressBar.FillChanged(Sender: TObject);
begin
  FillRect.Fill.Assign(FFill);
end;

procedure TRoundProgressBar.Resize;
begin
  inherited;
  UpdateWidths;
end;

procedure TRoundProgressBar.SetStroke(const Value: TStrokeBrush);
begin
  FStroke.Assign(Value);
end;

procedure TRoundProgressBar.StrokeChanged(Sender: TObject);
begin
  StrokeRect.Stroke.Assign(FStroke);
end;

procedure TRoundProgressBar.UpdateWidths;
begin
  FillRect.Width := Width;
  FillLayout.Width := Width * (FProgress / 100);
  Repaint;
end;
+4

, , ( Rectf). :

1) onpaint trectangle ( )

2) 2 Trectangles ( ), tRectangle (), , ( Sides Trectangle) Trectangle (), ( ). 2 Trectangles Tlayout ( , ), Trectangle () Trectangle () ALleft. , MyOrangeRect.width: = XX, xx -

+1

TRectangle:

TRectangle, , fill TBitmap.

TBitmap ( ) fill.bitmap.bitmap( double bitmap) .

- .

: , Photoshop, / , IOS TRectangle.

+1

(roundrect), :

progress image1

progress image2

procedure TForm4.SpinBox1Change(Sender: TObject);
begin
roundrect2.Width:=strtoint(SpinBox1.Text);
end;

, ;

0

TRectangle , .

The best solution for you would be to create a custom component that contains two TPathData(calling them, for example, PathBackground and PathFill), which are recalculated when the percentage changes and when it changes.

In the Paint routine, I would draw this path

Canvas.FillPath(PathBackground, ...);
Canvas.FillPath(PathFill, ...);
Canvas.DrawPath(PathBackground, ...);

By pulling the edge as the last, you avoid rendering errors.

0
source

Source: https://habr.com/ru/post/1670296/


All Articles