自定义GridPanel ControlItems问题

时间:2016-03-02 09:10:40

标签: delphi delphi-10-seattle

我将TGridPanel子类化为我的控件TMyGridPanel

我这样做是因为我想在GridPanel中添加4个默认按钮。

所以我覆盖constructor并创建如下按钮:

constructor TMyGridPanel.Create(AOwner: TComponent);
var
  i: Integer;
  btn: TButton;
begin
  inherited Create(AOwner);

  for i := 0 to 3 do
  begin
    btn := TButton.Create(Self);
    btn.Parent := Self;
    btn.Align := alClient;
    btn.Caption := 'Hello World';    
    btn.Visible := True;
  end;
end;

这很好用。 ControlCollection Items属性显示4个按钮为CollectionItems

现在我想要复制并粘贴(复制)我的控件,因为我想要有2个。 但是,当我这样做时,按钮不会显示在控件中。

ControlCollection Items属性显示4个Collection Items但它们没有名称(空)。 当我关闭表格并重新打开时,按钮出现。

我正试图解决这个问题已经有好几天但是无法弄明白。

1 个答案:

答案 0 :(得分:3)

问题:

将面板组件复制到剪贴板时,其所有已发布的属性都会流式传输到文本中(将其粘贴到记事本中以查看其外观)。

粘贴到表单会从此文本重新构建组件。

由于Vcl.ExtCtrls.TGridPanel属性在published中定义为object MyGridPanel1: TMyGridPanel Left = 64 ... ControlCollection = < item Column = 0 Control = Button9 Row = 0 end item Column = 1 Control = Button10 Row = 0 end ... object Button9: TButton Left = 1 ... end object Button10: TButton Left = 92 ... end ... end ,因此其中的按钮包含在此文本中。这是一段摘录:

TMyGridPanel

粘贴时,IDE设计者首先创建一个类TMyGridPanel的新对象。在此步骤中,TMyGridPanel的构造函数会创建一组新按钮。

之后,所有已发布的属性都会从文本中重建,包括其中的ControlCollection和Buttons,这就是问题所在。

可能的解决方案:

在这种情况下,可能的解决方案是将TCustomGridPanel的父类更改为TMyGridPanel2 = class(TCustomGridPanel) ...

TCustomGridPanel

TCustom...(与其他TCustom...组件类似)不会发布任何属性,因此不会将其流式传输到剪贴板。

实际上从控件的TMyGridPanel2变体继承,而不是从Component Pallet中注册的变量继承,是子组件的正确方法。

如果我们现在将object MyGridPanel21: TMyGridPanel2 Left = 184 Top = 200 Width = 185 Height = 41 end 的此变体复制到剪贴板并将其粘贴到记事本中,我们可以看到没有其他属性:

TGridPanel

缺点:

这种方法有效,但有几个缺点需要注意:

  • 您无法访问Object Inspector中published引入的自定义属性(但您可以在运行时访问它们)。 将属性带回Object Inspector的解决方法是将其添加到组件的TMyGridPanel2 = class(TCustomGridPanel) public ... published property BorderStyle; property ColumnCollection; property RowCollection; ... end; 部分中:

    unit MyGridPanel2;
    
    interface
    
    uses
      Classes, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Controls;
    
    type
      TMyGridPanel2 = class(TCustomGridPanel)
      private
      public
        constructor Create(AOwner: TComponent); override;
      published
      end;
    
    procedure Register;
    
    implementation
    
    { TMyGridPanel2 }
    
    constructor TMyGridPanel2.Create(AOwner: TComponent);
    var
      i: Integer;
      btn: TButton;
    begin
      inherited Create(AOwner);
    
      for i := 0 to 3 do
      begin
        btn := TButton.Create(Self);
        btn.Parent := Self;
        btn.Align := alClient;
        btn.Caption := 'Hello World';
        btn.Visible := True;
      end;
    end;
    
    procedure Register;
    begin
      RegisterComponents('Custom', [TMyGridPanel2]);
    end;
    
    end.
    
  • 您无法通过Object Inspector更改四个按钮的属性,也不能将事件附加到它们。你必须在代码中这样做。

    实际上这是好行为。当您创建具有子控件的复合组件时,最好将所有功能都包含在组件本身中。

完整代码示例:

let menuItem = NSMenuItem()
menuItem.title = object.name!
menuItem.keyEquivalent = object.shortcut!
menuItem.representedObject = object
menuItem.action = "testSelector:"
appDel.menu.insertItem(menuItem, atIndex: 0)

func testSelector(sender: NSMenuItem) {
    let object = (sender.representedObject as! MyNewObject)
    print("Name of set:", object.name)
}

首先在测试项目中尝试此操作,而不是在生产中。