如何处理复合组件中子项的双击?

Posted

技术标签:

【中文标题】如何处理复合组件中子项的双击?【英文标题】:How to handle double click from childs in compound component? 【发布时间】:2017-04-02 03:22:48 【问题描述】:

我创建了一个基于TCustomPanel 的新复合组件。 在它上面我有两个标签和一个图像,覆盖了所有的表面,看这个布局(下部不太重要):

我的问题是如何导出这些控件的双击功能?是否可以使用新控件的双击(事件)来管理其上的子控件?

【问题讨论】:

您是否希望所有控件同时响应 dblclick 或是否希望每个 ctrl 都有自己的 dblclick 事件处理程序,这不是很清楚。 【参考方案1】:

我认为您应该使用以下方法来做到这一点:

    OnDblClick 事件添加到复合组件。 在复合组件中添加一个名为FOnInternalDblClick(名称不重要)的方法,与TNotifyEvent 兼容。 在FOnInternalDblClick内部,执行复合组件的OnDblClick。 在复合组件的构造函数中,将FOnInternalDblClick 分配给您要为其管理事件的每个组件的OnDblClick 事件。

示例代码:

TMyCompoundComponent = class(TCustomPanel)
protected
  FOnDblClick : TNotifyEvent;
  procedure FOnInternalDblClick(ASender : TObject);
public
  constructor Create(AOwner : TComponent); override;
published
  property OnDblClick : TNotifyEvent read FOnDblClick write FOnDblClick;
end;

constructor TMyCompoundComponent.Create(AOwner : TComponent);
begin
  inherited;
  //Lab1.OnDblClick := FOnInternalDblClick;
  //Lab2.OnDblClick := FOnInternalDblClick;
  //...
end;

procedure TMyCompoundComponent.FOnInternalDblClick(ASender : TObject);
begin
  if(Assigned(FOnDblClick))
  then FOnDblClick(ASender);
end;

注意:

在复合组件的OnDblClick 事件处理程序中,ASender 参数将是内部组件(Lab1Lab2Lab3...)。如果您希望将复合组件本身作为ASender 参数接收,您可以通过传递Self 而不是ASender 来更改FOnInternalDblClick 方法:

procedure TMyCompoundComponent.FOnInternalDblClick(ASender : TObject);
begin
  if(Assigned(FOnDblClick))
  then FOnDblClick(Self);
end;

【讨论】:

Tnx 很多,正是我需要的。最好的问候。 你应该坚持经典的“if assignment()...”【参考方案2】:

您的两个请求都是可能的。这取决于你想做什么。如果您希望能够在程序中为每个子项分别编写代码,则需要为组件创建三个额外的已发布属性并将它们映射到相应的子组件属性。像这样(仅显示一个子组件 - 对其他 2 个重复):

type
  TMyPanelForm1 = class( TPanel )
  private
    fLabel1, fLabel2 : TLabel;
    fImage : TImage;
    procedure SetLabel1DblClick(const Value: TNotifyEvent);
    function GetLabel1DblClick: TNotifyEvent;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property OnLabel1DblClick : TNotifyEvent
             read GetLabel1DblClick write SetLabel1DblClick;
  end;
...
function TMyPanelForm1.GetLabel1DblClick: TNotifyEvent;
begin
  Result := fLabel1.OnDblClick;
end;

procedure TMyPanelForm1.SetLabel1DblClick(const Value: TNotifyEvent);
begin
  fLabel1.OnDblClick := Value;

end;

另一方面,如果你想让控件像一个统一的控件一样工作,所有三个子控件都“继承”主组件双击,你只需像这样降低分配:

  TMyPanelForm2 = class( TPanel )
  private
    fLabel1, fLabel2 : TLabel;
    fImage : TImage;
    function GetOnDblClick: TNotifyEvent;
    procedure SetOnDblClick(const Value: TNotifyEvent);
  public
    constructor Create(AOwner: TComponent); override;
  published
    property OnDblClick : TNotifyEvent
             read GetOnDblClick write SetOnDblClick;
  end;
...
function TMyPanelForm2.GetOnDblClick: TNotifyEvent;
begin
  Result := inherited OnDblClick;
end;

procedure TMyPanelForm2.SetOnDblClick(const Value: TNotifyEvent);
begin
  inherited OnDblClick := Value;
  fLabel1.OnDblClick := Value;
  fLabel2.OnDblClick := Value;
  fImage.OnDblClick := Value;
end;

其他解决方案也是可能的。

【讨论】:

Tnx Dsm,实际上是第二种解决方案。我也尝试过这种方法,但我错过了一部分。

以上是关于如何处理复合组件中子项的双击?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理组件中的 isDirty?

如何处理样式组件中的条件

为啥 ReactJS 中一个组件的 css 文件与另一个组件的 css 文件交互?如何处理?

使用组件依赖时如何处理多个 Dagger 组件

openfire 外部组件如何处理存在和订阅?

如何处理 React / Flux 组件中的状态转换