使用:Lazarus 1.2.0; Windows 32位应用程序
我编写了一个从TPanel派生的自定义组件,它拥有4个TEdit控件。我已经为TEdits编写了OnClick事件处理程序代码。但是它不能在运行时工作,即事件不会触发。我不确定我错过了什么。请你告诉我我做错了什么?
组件代码如下:
unit uEditPanel;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
type
{ TEditPanel }
TEditPanel = class(TCustomPanel)
Edit0: TEdit;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
procedure SetEdit1OnClick(const AEvent: TNotifyEvent);
procedure SetEdit2OnClick(const AEvent: TNotifyEvent);
procedure SetEdit3OnClick(const AEvent: TNotifyEvent);
procedure SetEdit4OnClick(const AEvent: TNotifyEvent);
private
{ Private declarations }
FEdit1OnClick: TNotifyEvent;
FEdit2OnClick: TNotifyEvent;
FEdit3OnClick: TNotifyEvent;
FEdit4OnClick: TNotifyEvent;
function GetEdit0Text: string;
procedure SetEdit0Text(AText: string);
function GetEdit1Text: string;
procedure SetEdit1Text(AText: string);
function GetEdit2Text: string;
procedure SetEdit2Text(AText: string);
function GetEdit3Text: string;
procedure SetEdit3Text(AText: string);
function GetEdit4Text: string;
procedure SetEdit4Text(AText: string);
protected
{ Protected declarations }
procedure DoEdit1Click;
procedure DoEdit2Click;
procedure DoEdit3Click;
procedure DoEdit4Click;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
published
{ Published declarations }
property Edit0Text: string read GetEdit0Text write SetEdit0Text;
property Edit1Text: string read GetEdit1Text write SetEdit1Text;
property Edit2Text: string read GetEdit2Text write SetEdit2Text;
property Edit3Text: string read GetEdit3Text write SetEdit3Text;
property Edit4Text: string read GetEdit4Text write SetEdit4Text;
property OnEdit1Click: TNotifyEvent read FEdit1OnClick write SetEdit1OnClick;
property OnEdit2Click: TNotifyEvent read FEdit2OnClick write SetEdit2OnClick;
property OnEdit3Click: TNotifyEvent read FEdit3OnClick write SetEdit3OnClick;
property OnEdit4Click: TNotifyEvent read FEdit4OnClick write SetEdit4OnClick;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Standard', [TEditPanel]);
end;
{ TEditPanel }
procedure TEditPanel.SetEdit1OnClick(const AEvent: TNotifyEvent);
begin
FEdit1OnClick := AEvent;
end;
procedure TEditPanel.SetEdit2OnClick(const AEvent: TNotifyEvent);
begin
FEdit2OnClick := AEvent;
end;
procedure TEditPanel.SetEdit3OnClick(const AEvent: TNotifyEvent);
begin
FEdit3OnClick := AEvent;
end;
procedure TEditPanel.SetEdit4OnClick(const AEvent: TNotifyEvent);
begin
FEdit4OnClick := AEvent;
end;
function TEditPanel.GetEdit0Text: string;
begin
Result := Edit0.Text;
end;
procedure TEditPanel.SetEdit0Text(AText: string);
begin
Edit0.Text := AText;
end;
function TEditPanel.GetEdit1Text: string;
begin
Result := Edit1.Text;
end;
procedure TEditPanel.SetEdit1Text(AText: string);
begin
Edit1.Text := AText;
end;
function TEditPanel.GetEdit2Text: string;
begin
Result := Edit2.Text;
end;
procedure TEditPanel.SetEdit2Text(AText: string);
begin
Edit2.Text := AText;
end;
function TEditPanel.GetEdit3Text: string;
begin
Result := Edit3.Text;
end;
procedure TEditPanel.SetEdit3Text(AText: string);
begin
Edit3.Text := AText;
end;
function TEditPanel.GetEdit4Text: string;
begin
Result := Edit4.Text;
end;
procedure TEditPanel.SetEdit4Text(AText: string);
begin
Edit4.Text := AText;
end;
procedure TEditPanel.DoEdit1Click;
begin
if Assigned(FEdit1OnClick) then
FEdit1OnClick(Self);
end;
procedure TEditPanel.DoEdit2Click;
begin
if Assigned(FEdit2OnClick) then
FEdit2OnClick(Self);
end;
procedure TEditPanel.DoEdit3Click;
begin
if Assigned(FEdit3OnClick) then
FEdit3OnClick(Self);
end;
procedure TEditPanel.DoEdit4Click;
begin
if Assigned(FEdit4OnClick) then
FEdit4OnClick(Self);
end;
constructor TEditPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Edit0 := TEdit.Create(Self);
Edit1 := TEdit.Create(Self);
Edit2 := TEdit.Create(Self);
Edit3 := TEdit.Create(Self);
Edit4 := TEdit.Create(Self);
Edit0.Parent := Self;
Edit1.Parent := Self;
Edit2.Parent := Self;
Edit3.Parent := Self;
Edit4.Parent := Self;
Edit0.SetSubComponent(True);
Edit1.SetSubComponent(True);
Edit2.SetSubComponent(True);
Edit3.SetSubComponent(True);
Edit4.SetSubComponent(True);
Edit1.ReadOnly := True;
Edit2.ReadOnly := True;
Edit3.ReadOnly := True;
Edit4.ReadOnly := True;
Edit1.OnClick := FEdit1OnClick;
Edit2.OnClick := FEdit2OnClick;
Edit3.OnClick := FEdit3OnClick;
Edit4.OnClick := FEdit4OnClick;
Caption := EmptyStr;
Height := 117;
Width := 289;
BevelOuter := bvNone;
ClientHeight := 117;
ClientWidth := 289;
Edit0.Left := 0;
Edit0.Height := 21;
Edit0.Top := 0;
Edit0.Width := 288;
Edit0.BorderStyle := bsNone;
Edit0.TabOrder := 0;
Edit1.Left := 0;
Edit1.Height := 21;
Edit1.Top := 24;
Edit1.Width := 288;
Edit1.BorderStyle := bsNone;
Edit1.TabOrder := 1;
Edit1.Font.Color := clGray;
Edit2.Left := 0;
Edit2.Height := 21;
Edit2.Top := 48;
Edit2.Width := 288;
Edit2.BorderStyle := bsNone;
Edit2.TabOrder := 2;
Edit2.Font.Color := clGray;
Edit3.Left := 0;
Edit3.Height := 21;
Edit3.Top := 72;
Edit3.Width := 288;
Edit3.BorderStyle := bsNone;
Edit3.TabOrder := 3;
Edit3.Font.Color := clGray;
Edit4.Left := 0;
Edit4.Height := 21;
Edit4.Top := 96;
Edit4.Width := 288;
Edit4.BorderStyle := bsNone;
Edit4.TabOrder := 4;
Edit4.Font.Color := clGray;
end;
end.
在运行时,我的组件如下所示:
答案 0 :(得分:2)
我建议采用以下方法。它不仅可以确保各种OnClick
事件正常工作,还可以整合所有重复的代码,以便于管理:
type
TEditPanel = class(TCustomPanel)
private
{ Private declarations }
FEdits: array[0..4] of TEdit;
FEditOnClick: array[1..4] of TNotifyEvent;
function GetEditOnClick(Index: Index): TNotifyEvent;
procedure SetEditOnClick(Index: Index; const AEvent: TNotifyEvent);
function GetEditText(Index: Integer): string;
procedure SetEditText(Index: Integer; const AText: string);
protected
{ Protected declarations }
procedure DoEditClick(Sender: TObject);
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
published
{ Published declarations }
property Edit0Text: string read GetEditText write SetEditText index 0;
property Edit1Text: string read GetEditText write SetEditText index 1;
property Edit2Text: string read GetEditText write SetEditText index 2;
property Edit3Text: string read GetEditText write SetEditText index 3;
property Edit4Text: string read GetEditText write SetEditText index 4;
property OnEdit1Click: TNotifyEvent read GetEditOnClick write SetEditOnClick index 1;
property OnEdit2Click: TNotifyEvent read GetEditOnClick write SetEditOnClick index 2;
property OnEdit3Click: TNotifyEvent read GetEditOnClick write SetEditOnClick index 3;
property OnEdit4Click: TNotifyEvent read GetEditOnClick write SetEditOnClick index 4;
end;
procedure TEditPanel.GetEditOnClick(Index: Integer): TNotifyEvent;
begin
Result := FEditOnClick[Index];
end;
procedure TEditPanel.SetEditOnClick(Index: Integer; const AEvent: TNotifyEvent);
begin
FEditOnClick[Index] := AEvent;
end;
function TEditPanel.GetEditText(Index: Integer): string;
begin
Result := FEdits[Index].Text;
end;
procedure TEditPanel.SetEditText(Index: Integer; const AText: string);
begin
FEdits[Index].Text := AText;
end;
procedure TEditPanel.DoEditClick(Sender: TObject);
var
Evt: TNotifyEvent;
begin
Evt := FEditOnClick[TEdit(Sender).Tag];
if Assigned(Evt) then
Evt(Self);
end;
constructor TEditPanel.Create(AOwner: TComponent);
var
I: Integer;
begin
inherited Create(AOwner);
Caption := EmptyStr;
Height := 117;
Width := 289;
BevelOuter := bvNone;
ClientHeight := 117;
ClientWidth := 289;
for I := 0 To 4 do
begin
FEdits[I] := TEdit.Create(Self);
FEdits[I].Parent := Self;
FEdits[I].SetSubComponent(True);
FEdits[I].ReadOnly := True;
FEdits[I].Left := 0;
FEdits[I].Height := 21;
FEdits[I].Top := 24 * I;
FEdits[I].Width := 288;
FEdits[I].BorderStyle := bsNone;
FEdits[I].TabOrder := I;
if I > 0 then
begin
FEdits[I].Tag := I;
FEdits[I].Font.Color := clGray;
FEdits[I].OnClick := DoEditClick;
end;
end;
end;
答案 1 :(得分:1)
您将事件存储到字段中,但不设置控件事件。
constructor TEditPanel.Create(AOwner: TComponent);
begin
...
// Assign the current value, but is nil at this moment
Edit1.OnClick := FEdit1OnClick;
...
end;
procedure TEditPanel.SetEdit1OnClick(const AEvent: TNotifyEvent);
begin
// set a new value only to the field
FEdit1OnClick := AEvent;
end;
字段和编辑控件事件处理程序没有魔术值传输。您还必须将值设置为控件事件。
但您可以直接从控件访问事件属性,就像使用Text
属性一样。
你应该看一下重复代码来简化/缩短它。
unit uEditPanel;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
type
{ TEditPanel }
TEditPanel = class( TCustomPanel )
private
Edit0 : TEdit;
Edit1 : TEdit;
Edit2 : TEdit;
Edit3 : TEdit;
Edit4 : TEdit;
{ Private declarations }
function GetEditOnClick( const Index : Integer ) : TNotifyEvent;
function GetEditText( const Index : Integer ) : string;
procedure SetEditOnClick( const Index : Integer; const Value : TNotifyEvent );
procedure SetEditText( const Index : Integer; const Value : string );
procedure InitEdit( AEdit : TEdit; ATop, ATabOrder : Integer; AReadOnly : Boolean );
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create( AOwner : TComponent ); override;
published
{ Published declarations }
property Edit0Text : string index 0 read GetEditText write SetEditText;
property Edit1Text : string index 1 read GetEditText write SetEditText;
property Edit2Text : string index 2 read GetEditText write SetEditText;
property Edit3Text : string index 3 read GetEditText write SetEditText;
property Edit4Text : string index 4 read GetEditText write SetEditText;
property OnEdit1Click : TNotifyEvent index 1 read GetEditOnClick write SetEditOnClick;
property OnEdit2Click : TNotifyEvent index 2 read GetEditOnClick write SetEditOnClick;
property OnEdit3Click : TNotifyEvent index 3 read GetEditOnClick write SetEditOnClick;
property OnEdit4Click : TNotifyEvent index 4 read GetEditOnClick write SetEditOnClick;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents( 'Standard', [TEditPanel] );
end;
{ TEditPanel }
function TEditPanel.GetEditOnClick( const Index : Integer ) : TNotifyEvent;
begin
case index of
0 :
Result := Edit0.OnClick;
1 :
Result := Edit1.OnClick;
2 :
Result := Edit2.OnClick;
3 :
Result := Edit3.OnClick;
4 :
Result := Edit4.OnClick;
end;
end;
function TEditPanel.GetEditText( const Index : Integer ) : string;
begin
case index of
0 :
Result := Edit0.Text;
1 :
Result := Edit1.Text;
2 :
Result := Edit2.Text;
3 :
Result := Edit3.Text;
4 :
Result := Edit4.Text;
end;
end;
procedure TEditPanel.SetEditOnClick( const Index : Integer; const Value : TNotifyEvent );
begin
case index of
0 :
Edit0.OnClick := Value;
1 :
Edit1.OnClick := Value;
2 :
Edit2.OnClick := Value;
3 :
Edit3.OnClick := Value;
4 :
Edit4.OnClick := Value;
end;
end;
procedure TEditPanel.SetEditText( const Index : Integer; const Value : string );
begin
case index of
0 :
Edit0.Text := Value;
1 :
Edit1.Text := Value;
2 :
Edit2.Text := Value;
3 :
Edit3.Text := Value;
4 :
Edit4.Text := Value;
end;
end;
procedure TEditPanel.InitEdit( AEdit : TEdit; ATop, ATabOrder : Integer; AReadOnly : Boolean );
begin
AEdit.Parent := Self;
AEdit.SetSubComponent( True );
AEdit.ReadOnly := AReadOnly;
AEdit.Left := 0;
AEdit.Top := ATop;
AEdit.Height := 21;
AEdit.Width := 288;
AEdit.BorderStyle := bsNone;
AEdit.TabOrder := ATabOrder;
if AReadOnly
then
AEdit.Color := clGray;
end;
constructor TEditPanel.Create( AOwner : TComponent );
begin
inherited Create( AOwner );
Caption := EmptyStr;
Height := 117;
Width := 289;
BevelOuter := bvNone;
ClientHeight := 117;
ClientWidth := 289;
Edit0 := TEdit.Create( Self );
Edit1 := TEdit.Create( Self );
Edit2 := TEdit.Create( Self );
Edit3 := TEdit.Create( Self );
Edit4 := TEdit.Create( Self );
InitEdit( Edit0, 0, 0, False );
InitEdit( Edit1, 24, 1, True );
InitEdit( Edit2, 48, 2, True );
InitEdit( Edit3, 72, 3, True );
InitEdit( Edit4, 96, 4, True );
end;
end.
如果使用数组管理编辑控件,您的代码可以写得非常短,甚至会变短。