Delphi TFlowPanel中的自动调整大小和自动换行冲突

Delphi TFlowPanel中的自动调整大小和自动换行冲突,delphi,delphi-xe2,vcl,autosize,Delphi,Delphi Xe2,Vcl,Autosize,我尝试以下列方式使用TFlowPanel组件: 放置在主窗体上Form1组件flowPanel 1:TFlowPanel 设置Form1.Width=400,FlowPanel1.Align=alTop,FlowPanel1.AutoSize=True,FlowPanel1.AutoWrap=True 在流程面板1上放置5个速度按钮,并将其宽度设置为64 编译并运行 减小表单的宽度(大约Form1.width=200) 由于某些原因,当用户调整窗体大小时,speedbuttons不会自动排列成两

我尝试以下列方式使用TFlowPanel组件:

  • 放置在主窗体上
    Form1
    组件
    flowPanel 1:TFlowPanel
  • 设置
    Form1.Width=400
    FlowPanel1.Align=alTop
    FlowPanel1.AutoSize=True
    FlowPanel1.AutoWrap=True
  • 流程面板1上放置5个速度按钮,并将其
    宽度设置为64
    
  • 编译并运行
  • 减小表单的宽度(大约
    Form1.width=200
  • 由于某些原因,当用户调整窗体大小时,speedbuttons不会自动排列成两行。尽管如此,当
    AutoSize=False
    AutoWrap=True
    时,它们会排成两行 这种行为的原因是什么?如何解决

    编辑:我找到了“又快又脏”的解决方案。以下代码是
    TFlowPanel.OnResize
    事件的事件处理程序:

    procedure TForm1.FlowPanel1Resize(Sender: TObject);
    begin
      with FlowPanel1 do
      begin
        AutoSize := False;
        Realign;            // line up controls
        AutoSize := True;   // adjust TFlowPanel.Height
      end;
    end;
    

    然而,我仍然想知道是否有一种标准的方法来解决这个问题。

    我无法在代码中找到这种行为的确切原因,但基本上你已经挑战了两个大小属性,和。问题是,我认为,当您调整窗体大小时,配置为True并设置为的控件将首先尝试自动调整控件大小,然后与其父控件顶部对齐。我可以肯定的是,至少从逻辑意义上讲,这两个属性不应该组合在一起

    我建议您的解决方法是在默认情况下关闭自动调整大小,并在事件中临时打开并返回关闭以自动调整高度。因此,在代码中,它将简单地更改为:

    procedure TForm1.FlowPanel1Resize(Sender: TObject);
    begin
      // there's no Realign here, since the AlignControls request is called
      // at control resize, so here you have children already aligned, what
      // you then need is to request the control to autosize the height and
      // turn off the autosizing to the default, disabled state
      FlowPanel1.AutoSize := True;
      FlowPanel1.AutoSize := False;
    end;
    
    tl,dr:这是
    TFlowPanel
    中的一个bug


    通常情况下,
    AutoSize
    Align
    属性在默认情况下配合得非常好,因为这在
    TControl
    级别已经得到了处理,所以我想知道为什么会发生这种情况。我注意到
    TFlowPanel
    中有一个被重写的
    AlignControls
    方法,并考虑绕过它进行测试:

    type
      TWinControlAccess = class(TWinControl);
      TAlignControls = procedure(Instance: TObject; AControl: TControl;
        var Rect: TRect);
    
      TFlowPanel = class(Vcl.ExtCtrls.TFlowPanel)
      protected
        procedure AlignControls(AControl: TControl; var Rect: TRect); override;
      end;
    
      TForm1 = class(TForm)
        ...
    
    procedure TFlowPanel.AlignControls(AControl: TControl; var Rect: TRect);
    begin
      // Skip TCustomFlowPanel.AlignControls
      TAlignControls(@TWinControlAccess.AlignControls)(Self, AControl, Rect);
    end;
    
    procedure TForm1.FlowPanel1Resize(Sender: TObject);
    begin
      // Do my own aligning of the last button
      if FlowPanel1.ClientWidth < Button5.BoundsRect.Right then
      begin
        Button5.Left := 1;
        Button5.Top := Button1.Height + 1;
      end
      else if FlowPanel1.ClientWidth > Button4.BoundsRect.Right + Button5.Width then
      begin
        Button5.Left := Button4.BoundsRect.Right;
        Button5.Top := 1;
      end;
    end;
    

    当注释掉该部分时,行为与设置的
    Align
    一样。现在,我想把这个提交给QC,但也许我忽略了它的一些方面。当确实需要此代码时(以及为什么需要此代码),请进行编辑或评论。

    +1表示更短更好的代码;默认情况下,对齐和自动调整不合并。
    AutoSize
    Align
    在默认情况下配合良好,请参阅。不过短一点不错+1+1,我也一直在怀疑,但不确定。尽管如此,我还是宁愿避免在我的表单中将
    AutoSize
    Align
    组合在一起(可能是因为逻辑原因和过去的一些不好的经验:-),我刚刚用
    AutoSize=True
    Align=alTop
    WordWrap=True
    标题中的一些长文本尝试了TLabel组件。似乎也存在同样的问题:调整表单的大小不会导致调整TLabel的高度。此外,@TLama提出的同一个两行缩写器也可以很好地工作。
    TLabel
    有自己重新引入的
    AutoSize
    属性,我现在敢说,它也有一个错误的实现。这同样适用于
    TStaticText
    等。。。仔细想想,我真的不明白为什么这些控件重新引入了
    AutoSize
    属性,或者为什么它们的行为不像
    t(Win)控件中实现的那样。这与
    TToolBar
    相比,它不会因自己的
    AutoSize
    实现而隆隆作响,而是对
    TControl
    的实现感到满意,并因此自动调整大小。谢谢,我现在看到TToolBar自动调整大小正确。然而,我不能评论你关于TFlowPanel中bug的回答,因为我从来没有深入研究过VCL源代码(也许我应该?)。也许我会继续使用简单的解决方法。
    if AutoSize then
      Rect := TRect.Create(
        Rect.Left,
        Rect.Top,
        Rect.Left + (ExplicitWidth - (Width - (Rect.Right - Rect.Left))),
        Rect.Top + (ExplicitHeight - (Height - (Rect.Bottom - Rect.Top))));