Delphi 如何使用Align属性调整TFlowPanel内控件的大小?
我在Delphi 如何使用Align属性调整TFlowPanel内控件的大小?,delphi,flowpanel,Delphi,Flowpanel,我在TFlowPanel中有几个控件(即TDBChart)。当用户单击其中一个时,我希望它填充整个流面板的客户区。但是,在运行时更改流面板中子控件的可见和对齐属性似乎没有任何效果。这有什么特别的窍门吗?我找到了reallign()方法,但它似乎对控件的布局没有任何影响。以下是我的OnClick事件的代码: var AChart: TDBChart; V: Boolean; i: Integer; begin AChart := TDBChart(Sender); if ACh
TFlowPanel
中有几个控件(即TDBChart
)。当用户单击其中一个时,我希望它填充整个流面板的客户区。但是,在运行时更改流面板
中子控件的可见
和对齐
属性似乎没有任何效果。这有什么特别的窍门吗?我找到了reallign()
方法,但它似乎对控件的布局没有任何影响。以下是我的OnClick
事件的代码:
var
AChart: TDBChart;
V: Boolean;
i: Integer;
begin
AChart := TDBChart(Sender);
if AChart.Align = alNone then
begin
V := False;
AChart.Align := alClient;
end else begin
V := True;
AChart.Align := alNone;
end;
for i := 0 to FlowPanel1.ControlCount - 1 do
if FlowPanel1.Controls[i] is TDBChart then
if FlowPanel1.Controls[i] <> AChart then
FlowPanel1.Controls[i].Visible := V;
end;
var
AChart:TDBChart;
V:布尔型;
i:整数;
开始
AChart:=TDBChart(发送方);
如果AChart.Align=alNone,则
开始
V:=假;
AChart.Align:=alClient;
结束,否则开始
V:=真;
AChart.Align:=alNone;
结束;
对于i:=0到FlowPanel1.ControlCount-1 do
如果FlowPanel1.Controls[i]为TDBChart,则
如果FlowPanel1.控制[i]AChart,则
FlowPanel1.控件[i]。可见:=V;
结束;
图表按预期隐藏或显示,但ADBChart
不会填充整个流程面板的客户区。流程面板不关心控件的对齐设置,就像不关心控件的位置一样-它的设计只是为了让它们流动
一种解决方案是派生一个新类并重写AlignControls
,并在其中相应地调整将填充曲面的控件的大小。例如:
type
TFlowPanel = class(extctrls.TFlowPanel)
protected
procedure AlignControls(AControl: TControl; var Rect: TRect); override;
end;
..
procedure TFlowPanel.AlignControls(AControl: TControl; var Rect: TRect);
var
i, VisibleCount, VisibleControl: Integer;
begin
VisibleCount := 0;
VisibleControl := 0;
for i := 0 to ControlCount - 1 do
if Controls[i].Visible then begin
Inc(VisibleCount);
VisibleControl := i;
end;
if (VisibleCount = 1) and (Controls[VisibleControl] = AControl) and
(AControl.Align = alClient) then begin
// preserve 'Explicit..' settings
AControl.ControlState := AControl.ControlState + [csAligning];
AControl.SetBounds(1, 1, ClientWidth - 1, ClientHeight -1);
AControl.ControlState := AControl.ControlState - [csAligning];
end;
inherited;
end;
然后,您可以将所有图表的单击事件设置为此处理程序:
var
AChart: TTDBChart;
procedure SetVisibility(Visible: Boolean);
var
i: Integer;
begin
for i := 0 to FlowPanel1.ControlCount - 1 do
if FlowPanel1.Controls[i] is TDBChart then
if FlowPanel1.Controls[i] <> AChart then
FlowPanel1.Controls[i].Visible := Visible;
end;
begin
AChart := TDBChart(Sender);
if AChart.Align = alNone then
begin
SetVisibility(False);
AChart.Align := alClient;
end else begin
AChart.Align := alNone; // set before changing visible
SetVisibility(True);
AChart.SetBounds(0, 0, AChart.ExplicitWidth, AChart.ExplicitHeight);
end;
end;
var
AChart:TTDBChart;
过程集合可见性(可见:布尔值);
变量
i:整数;
开始
对于i:=0到FlowPanel1.ControlCount-1 do
如果FlowPanel1.Controls[i]为TDBChart,则
如果FlowPanel1.控制[i]AChart,则
FlowPanel1.控件[i]。可见:=可见;
结束;
开始
AChart:=TDBChart(发送方);
如果AChart.Align=alNone,则
开始
设置可见性(假);
AChart.Align:=alClient;
结束,否则开始
AChart.Align:=alNone;//更改前设置为可见
设置可见性(真);
AChart.SetBounds(0,0,AChart.ExplicitWidth,AChart.ExplicitHeight);
结束;
结束;
我应该注意,这只适用于固定大小的flowpanel。根据设计,T(自定义)flowpanel
使用子控件的自定义对齐,这是通过重写的AlignControls
方法实现的
您可以通过跳过该默认行为,从它的祖先那里返回该默认行为来防止它。此外,不需要隐藏所有相邻控件。把点击的图表放在前面就足够了
type
TFlowPanel = class(Vcl.ExtCtrls.TFlowPanel)
private
FFlowDisabled: Boolean;
procedure SetFlowDisabled(Value: Boolean);
protected
procedure AlignControls(AControl: TControl; var Rect: TRect); override;
public
property FlowDisabled: Boolean read FFlowDisabled write SetFlowDisabled;
end;
...
{ TFlowPanel }
type
TWinControlAccess = class(TWinControl);
TAlignControls = procedure(Instance: TObject; AControl: TControl;
var Rect: TRect);
procedure TFlowPanel.AlignControls(AControl: TControl; var Rect: TRect);
begin
if FFlowDisabled then
// Skip inherited in TCustomFlowPanel:
TAlignControls(@TWinControlAccess.AlignControls)(Self, AControl, Rect)
else
inherited;
end;
procedure TFlowPanel.SetFlowDisabled(Value: Boolean);
begin
if FFlowDisabled <> Value then
begin
FFlowDisabled := Value;
Realign;
end;
end;
{ TForm1 }
procedure TForm1.DBChartClick(Sender: TObject);
const
FlowAligns: array[Boolean] of TAlign = (alNone, alClient);
var
Chart: TDBChart;
Panel: TFlowPanel;
DisableFlow: Boolean;
begin
Chart := TDBChart(Sender);
Panel := Chart.Parent as TFlowPanel;
DisableFlow := not Panel.FlowDisabled;
Chart.Align := FlowAligns[DisableFlow];
Chart.BringToFront;
Panel.FlowDisabled := DisableFlow;
end;
类型
TFlowPanel=class(Vcl.ExtCtrls.TFlowPanel)
私有的
FFlowDisabled:布尔值;
过程SetFlowDisabled(值:布尔);
受保护的
过程控制(a控制:t控制;var Rect:t控制);推翻
公众的
属性FlowDisabled:布尔读取FFlowDisabled写入SetFlowDisabled;
结束;
...
{TFlowPanel}
类型
TWinControlAccess=类(TWinControl);
TAlignControls=过程(实例:ToObject;AControl:TControl;
var-Rect:TRect);
程序TFlowPanel.AlignControls(A控制:TControl;变量Rect:TRect);
开始
如果禁用,则
//TCustomFlowPanel中继承的跳过:
TAlignControls(@TWinControlAccess.AlignControls)(Self、AControl、Rect)
其他的
继承;
结束;
过程TFlowPanel.SetFlowDisabled(值:布尔);
开始
如果FFlowDisabled值,则
开始
FFlowDisabled:=值;
重新排列
结束;
结束;
{TForm1}
过程TForm1.DBChartClick(发送方:TObject);
常数
FlowAligns:TAlign=(alNone,alClient)的数组[Boolean];
变量
图表:TDBChart;
面板:TFlowPanel;
禁用流:布尔;
开始
图表:=TDBChart(发送方);
面板:=图表。父级为TFlowPanel;
DisableFlow:=非面板。FlowDisabled;
Chart.Align:=流程对齐[禁用流程];
海图.布林托夫隆;
Panel.FlowDisabled:=禁用流;
结束;
工作起来很有魅力,但我必须硬编码AChart.explicittwith
和AChart.ExplicitHeight
。Thanks@iMan->“。必须硬编码..”>然后可以从“AlignControls”中删除“ControlState:=”语句。或者,相反,您可以尝试在设置对齐和可见性的同时在单击处理程序中设置标志。无论如何,不客气!很好的“放大流程面板”-问题!我想这也会考虑到一个可调整大小的flowpanel。@Sertac是的,我在所有锚都打开的情况下对它进行了测试。