我正在使用Delphi 5,我在运行时创建了许多面板,然后在面板上创建按钮,显然在运行时再次创建。我需要这样做,因为我可能需要在将来动态创建更多的面板/按钮组合。
我可以做到这一切,但是我不知道如何引用我创建的面板,因为我找不到访问面板组件名称的方法。在互联网上狩猎我发现我可以使用FindComponent按名称查找面板组件,但我仍然不知道如何使用该名称,因为我不能使用字符串变量来引用它 - 例如StringVar:= Panel.Name。我得到一个类型不匹配,TComponentName与String。
我在创建面板时为每个面板创建了按钮。简化,它看起来像这样:
With TypeQuery do begin // Create Panels
First;
While (not eof) do begin // create the actual panel
panelno := FieldByName('Product_type_id').AsInteger;
pnl := Tpanel.Create(Self);
pnl.name := FieldByName('PanelName').AsString;
pnl.color := clInactiveCaption;
pnl.parent := MainForm;
pnl.width := 365;
pnl.Height := 551;
pnl.left := 434
pnl.top := 122;
pnl.caption := '';
With ButtonQuery do begin
Close;
Parameters.parambyname('PanelID').Value := PanelNo;
Open;
First;
While (not eof) and (FieldByName('Product_type_id').AsInteger = PanelNo) do begin //put the buttons on it.
btnName := FieldByName('ButtonName').AsString;
BtnText := FieldByName('ButtonText').AsString;
BtnGroup := FieldByName('Product_Group_ID').AsString;
GrpColour := FieldByName('ButtonColour').AsString;
btn := TColorButton.Create(Self);
btn.Parent := pnl;
btn.Name := BtnName;
Btn.backcolor := HexToTColor(GrpColour);
btn.Font.Name := 'Arial Narrow';
btn.Font.Style := [fsBold];
btn.Font.Size := 10;
. . .
end;
. . .
end;
end;
我在几个论坛(包括这个论坛)上读过,没有办法直接按名称引用面板。我尝试过使用组件数组,但我遇到了同样的问题 - 我需要通过指定的组件名称引用该组件。
好吧,我不是一个枪支程序员 - 我多年来一直使用Delphi来创建简单的程序,但这个程序要复杂得多。我之前从未使用过运行时组件。
我可以使用FindComponent使面板可见或不可见吗?如果是这样的话,鉴于我上面给你看过的内容,你能否给我一些我应该采取的方法?
提前致谢...
答案 0 :(得分:10)
我不确定你的意思是: " 我无法使用字符串变量来引用它 - 例如StringVar:= Panel.Name。"
试试这个:
procedure TForm1.FormCreate(Sender: TObject);
var
p: TPanel;
begin
p := TPanel.Create(Self); // create a TPanel at run-time
p.Name := 'MyPanel'; // set a unique name
p.Parent := Self;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
p: TPanel;
StringVar: string;
begin
p := FindComponent('MyPanel') as TPanel;
if Assigned(p) then // p has reference to MyPanel
begin
// use that reference
p.Caption := 'Foo';
StringVar := p.Name;
ShowMessage(StringVar);
end;
end;
或者我错过了什么?
答案 1 :(得分:6)
您将组件名称与变量名称混为一谈。对于IDE创建的组件,Delphi IDE努力保持这两者相同,但它们并不一定相同。您没有变量名称,因为您正在动态创建组件,并且您不知道需要多少变量。但是,您仍然可以控制组件名称:只需分配组件的Name
属性,然后通过调用FindComponent
,您可以像使用任何其他组件名称一样使用它。只需确保每个面板实例的名称都是唯一的。
还要记住处理变量的方法,当你在编译时不知道你需要多少时,就是使用 arrays 或 lists 。您可以使用普通旧数组,也可以使用更复杂的数据结构,例如TComponentList
或TDictionary
。
最后,为了更容易引用您正在创建的面板上的控件 ,您可以省去面板并使用框架。您可以在IDE中直观地设计TFrame
并为按钮指定名称,并且在运行时,您可以实例化框架类,它将自动为您创建所有按钮,就像您实例化表单一样或数据模块。您只需要为新的框架对象指定一个名称,但该对象已经有指向按钮的命名字段。
答案 2 :(得分:2)
不需要创建您创建的要在tForm实例上显示的项目的辅助列表。
AFAIK,无论何时创建一个使用Form或其他Container代替self
的新面板 pnl := Tpanel.Create(Self);
你不需要去处理新的pnl,因为它是由包含“self”组件处理的。
这意味着应该有任何构造来保存父组件的子组件。
我希望您可以在父对象中找到ComponentCount或Components列表或FindComponent方法。 假设“Self”引用的对象是Tform。
for i := 0 to tForm(self).ComponentCount -1 do
if tForm(self).Components[i] is tPanel then
tPanel(tForm(self).Components[i]).Caption := intToStr(i) ;
将更改应用程序中tPanel的所有Captions。 为了区分由代码和设计器创建的面板,您可以使用每个创建的tPanel的TAG属性并在上面的示例中使用它。
答案 3 :(得分:0)
您可以将需要引用的组件添加到TList | Container ...然后,使用列表|容器来访问它们
var
slPanels: TStringList;
...
With TypeQuery do begin // Create Panels
First;
While (not eof) do begin // create the actual panel
panelno := FieldByName('Product_type_id').AsInteger;
pnl := Tpanel.Create(Self);
pnl.name := FieldByName('PanelName').AsString;
slPanels.AddObject(FieldByName('PanelName').AsString, pnl);
当你需要它时:
TPanel(slPanels.Objects[slPanels.IndexOf(FieldByName('PanelName').AsString)]) ...
我不喜欢上面的代码(有更好的容器......但这应该做的工作:o))