Delphi TFlowPanel中的自动调整大小和自动换行冲突
我尝试以下列方式使用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不会自动排列成两
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))));