我在TDBChart
中有一些控件(即TFlowPanel
)。当用户点击其中一个时,我希望它填满整个flow panel
的客户区。但是,似乎在运行时更改visible
内的子控件的align
和flow panel
属性没有任何影响。这有什么特别的诀窍吗?我找到了Realign()
方法,但它似乎对控件的布局没有任何影响。这是我的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;
图表会按预期隐藏或显示,但ADBChart
不会填满整个flow panel
的客户区。
答案 0 :(得分:3)
按照设计,T(Custom)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;
答案 1 :(得分:2)
FlowPanel不关心其控件的对齐设置,就像它不关心它们的位置一样 - 它只是为了让它们流动而设计。
一种解决方案可以是派生一个新类并覆盖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;
我应该注意,这只适用于固定尺寸的流动面板。