【问题标题】:How to eliminate variables "panel1, panel2, panel3 .. etc." in Delphi?如何消除变量“panel1, panel2, panel3 .. etc.”在德尔福?
【发布时间】:2012-08-18 09:11:18
【问题描述】:

我有这种类型

type
 TMain = class(TForm)

 panel1: Tpanel;
 panel2: Tpanel;
 panel3: Tpanel;
 panel4: Tpanel;
 panel5: Tpanel;
 panel6: Tpanel;
 panel7: Tpanel;
 panel8: Tpanel;
 ......
 panel45: Tpanel;

 label1: TLabel;
 label2: TLabel;
 label3: TLabel;
 label4: TLabel;
 label5: TLabel;
 label6: TLabel;
 label7: TLabel;
 ...........
 label109: TLabel;

我怎样才能在一行中调用这些组件...在 Type 中?

谢谢...

更新....

从我得到并接受的 anwser 的基础上,当我拥有所有这些组件并从主窗体中进行 button1.click 之类的操作时,它的效果很好......

但我习惯从单位做出动作......所以

当我点击一个按钮时,我会看到一个过程 DoMaths(Sender: TObject);

procedure Tform1.DoMaths(Sender: TObject);
  begin
    if TButton1(Sender).hint := 'Make the standard Package' then
      do_Maths_standard_package;
  end;

do_Maths_standard_package 位于 ComplexMaths 单元中。

是过程do_Maths_standard_package表单单元ComplexMaths它调用Form1中的一些组件......比如Form1.label1等......

所以当我调用 RegisterClass(TLabel) 并从类型中删除 Tlabel 时,它会给出一个错误,它无法找到 Label1...

请有人帮助我不要从一开始就做洞程序......

再次感谢...

【问题讨论】:

  • 我建议你在一个新问题中转换更新部分...
  • 我为这个 Fabricio 制作了一个标志,并向版主发表评论,如果我可以在一个新问题中做到这一点或更新现有的一个没有遮阳篷......所以等等看......

标签: delphi optimization delphi-7


【解决方案1】:

您可以删除 TPanel 或 TLabel 的名称,然后它只存在于控件列表中,而不存在于表单的类型声明中。您要么需要留下一个标签和一个面板,要么 添加:

initialization
  RegisterClass(TPanel);
  RegisterClass(Tlabel);
end.

在表格的末尾。

这使得带有大量控件的表单更加整洁。

【讨论】:

  • 但是当我从一个单元调用面板时,我遇到了一个小问题,它说他找不到我调用的特定 Tpanel... 例如。 main.great.color := clred 它说它找不到很棒的面板...
  • 尝试在主窗体中添加一个(公共)过程:procedure SetGreat(col: TColor);然后调用这个。这行得通吗?
  • 不,我的朋友......而且比开始更复杂......谢谢......但是为什么一个单元不能从主窗体中理解 RegisterClass() 单元?
  • 如果表单上的一个面板有一个名称,您不需要注册该类 - Delphi 会自动完成。标签也一样。如果您需要以编程方式引用面板(或标签),您确实需要命名它(您可以遍历控件,但是..为什么?)这样表单对象声明中的面板和标签的数量等于您的数量必须在运行时引用-它们将具有有意义的名称而不是“Label1”,不是吗:)。主格式是任何其他格式 - .dpr 项目文件是真正的主程序。您可以尝试在那里注册课程,但我可以'
【解决方案2】:

使用TForm.Controls 数组:

var
  i: Integer;
  Pnl: TPanel;
begin
  for i := 0 to ControlCount - 1 do
    if Controls[i] is TPanel then
    begin
      Pnl := TPanel(Controls[i]);
      Pnl.Caption := 'This is panel ' + IntToStr(i);
    end;
end;

Delphi 自动为每个TWinControl 创建两个列表:

  • Controls 包含控件包含的所有 TControl 项的列表。

  • Components 是控件上所有TComponents 的列表。

请注意,所有Controls 都是Components,但并非所有Components 都是Controls;这就是为什么有两个列表。 (例如,TDataSetComponents 列表中,但不在Controls 列表中;另一方面,TEdit 将在两者中。)

您也可以使用相同的技术来遍历面板或其他容器上的组件 - 例如,TPanel 具有 ControlComponent 数组。

如果您真正想要的是减少 type 声明本身内的项目数量,请改为在运行时创建它们 - Delphi 会自动将它们添加到基于 OwnerParent 的数组中:

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  Panel: TPanel;
  Label: TLabel;
begin
  for i := 0 to 10 do
  begin
    Panel := TPanel.Create(Self);  // Set who frees it
    Panel.Parent := Self;   // Set display surface
    Panel.Align := alTop;
    Panel.Name := Format('Panel%d', [i]); // Not necessary
    Panel.Caption := Panel.Name;  

    // Add a label on each panel, just for fun.
    Label := TLabel.Create(Panel); // Panel will free label
    Label.Parent := Panel;         // Label will show on panel
    Label.Top := 10;
    Label.Left := 10;
    Label.Name := Format('Label%d', [i]);
    Label.Caption := Label.Caption;   // Not necessary
  end;
end;

请注意,自己创建它们不是“优化”,因为它只是将加载从 VCL 转移到您自己做。它会减小 .dfm 文件的大小,但不会加快您的代码或加载时间,这意味着您也无法直观地布置表单。 (维护你的代码也更难,因为你的控件有无意义的名字。当你在 6 个月后阅读代码时,知道LastNameEditEditLastName 是什么比Edit1 容易得多。)

【讨论】:

  • “所有组件都不是控件”-我敢打赌,您的意思是“并非所有组件都是控件”,或者“并非每个组件都是控件”:-)
  • @Arioch'The:谢谢。措辞可以稍作改进;固定。
【解决方案3】:

你可以使用数组:

panels : array[1..45] of TPanel; 

这将允许您创建一个控件数组,并通过索引访问和使用它们。

【讨论】:

  • 这是错误的。 :-) Delphi 在表单上自动创建TControlsTComponents 的列表,分别在TCustomForm.ControlsTCustomForm.Components 中。 (表单上的所有项目都是TComponents,但并非所有项目都是TControls - Components 列表包括Controls。)不要投票(技术上可以这样做),但这不是正确的做法除非您出于某种原因需要复制现有数组。
  • @Ken 我不确定这是错的。这只是您在答案的代码部分创建中所做的一部分。无论如何,这个问题有点弱,所以可能值得留一点余地。
  • @KenWhite 继续这一行 - 让我们摆脱控制,因为它只复制组件的一部分。让我们摆脱所有类似 Panel1 的成员,因为它们只复制对应的 Components[i] 值。 Reed 数组中的值正是它是面板数组,并且仅是面板数组。这对某些应用程序是否有用取决于上下文,但不一定是不合理的。
  • @Arioch'The:为什么?我们知道我们正在寻找 TControls,因此使用它意味着我们正在处理更少的项目,而 Reed 的回答增加了添加已包含在其他两个数组中的项目数组的开销。
  • 因为开发人员可能非常想拥有面板列表,即拥有控件列表。并非总是如此,但为什么不呢?为什么不能有我想要明确的按钮或面板阵列的任务?你想要控制吗?迭代组件并丢弃非控件。使用控件集合更舒适,可以说更快?当您只需要面板时,对于 usint array fo 面板也是如此。