Firemonkey使用stylebook隐藏圆角溢出

JvA*_*JvA 5 delphi firemonkey

在firemonkey我试图使用带圆角的矩形制作进度条.最简单的情况是一个矩形(进度条)和其中的第二个矩形(进展到现在).附上一个简单的例子.

带角落的进度条(油漆): 带角的进度条(油漆)

我尝试过以下的事情:

  1. 让第二个矩形也有圆角.这不起作用,因为如果第二个矩形非常短或几乎在最后,这些舍入将会改变.
  2. 使用clipchildren.这与隐藏html/css中的溢出几乎相同,但Delphi在此函数中不包括圆角.
  3. 创建一个应该绘制图像的TPath.我真的很想避免这种解决方案,因为它不使用样式簿.我更喜欢为所有样式使用一个样式,而不是在样式代码的代码中使用多个位置.

什么工作:

  • 有一个非常难看的方法来完成这项工作.我现在使用那种方法,但我真的希望你能帮助我找到另一种解决方案.丑陋的方法是:只使用一个矩形.用渐变画笔填充它,将两个渐变点设置在同一个地方,并使渐变本身为0度.当我要改变进度条的状态等时,这种方法的结果是很多丑陋的代码.

这是我们可以避免的,或者这是唯一可行的解​​决方案吗?

进度条目标(油漆): 进度条结果

先感谢您!

一月

DNR*_*DNR 4

我不确定你的意思

使用clipchildren。这与在 html/css 中隐藏溢出几乎相同,但 Delphi 在此功能中不包含圆角。

我通过使用一个矩形作为边框来实现这一点;其顶部是进度布局,其中包含另一个矩形。第二个矩形始终具有第一个矩形的尺寸(这意味着角看起来相同),布局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;
Run Code Online (Sandbox Code Playgroud)