delphi – 为什么我的自定义组件在更改属性时更新?
发布时间:2020-12-15 03:50:28 所属栏目:大数据 来源:网络整理
导读:我已经创建了一个基于TPaintBox的组件,TGridPaintBox.它基本上是一个添加了“网格功能”的paintbox.它不是数据网格.更像棋盘组件. 在对象资源管理器中,我可以设置某些属性.最重要的是我可以设置网格尺寸(跨/下两个单元格),还可以设置与图形有关的选项.细胞是
|
我已经创建了一个基于TPaintBox的组件,TGridPaintBox.它基本上是一个添加了“网格功能”的paintbox.它不是数据网格.更像棋盘组件.
在对象资源管理器中,我可以设置某些属性.最重要的是我可以设置网格尺寸(跨/下两个单元格),还可以设置与图形有关的选项.细胞是否应该是正方形,奇/偶细胞的颜色等 我的这个组件的第一个版本的属性直接在类上,当我更改了一个属性时,设计时间图被立即更新.随着组件的增长,我想组织我的属性一点更好,并介绍了一些“选项属性”,如绘图选项,行为选项等.介绍后,设计时间图不再像以前一样更新.更改属性后,我必须单击要更新的组件.谁能告诉我为什么会发生这种情况? 这是一个被删除的代码版本.我希望能解释这个行为: (PS:这是我的第一个组件,即使我自1997年以来一直在使用Delphi,所以如果任何人可以按照我的方式发现任何愚蠢的事情,请随时告诉我) unit GridPaintBox;
interface
type
TGridDrawOption = (gdoSquareCells,gdoCenterCells,gdoDrawCellEdges,gdoDrawFocus);
TGridDrawOptions = set of TGridDrawOption;
TGridOptions = class(TPersistent)
private
FCellsX : integer;
FCellsY : integer;
FDrawOptions : TGridDrawOptions;
public
constructor Create(aGridPaintBox : TGridPaintBox);
procedure Assign(Source : TPersistent); override;
published
property CellsX : integer read FCellsX write FCellsX;
property CellsY : integer read FCellsY write FCellsY;
property DrawOptions : TGridDrawOptions read FDrawOptions write FDrawOptions;
end;
TGridPaintBox = class(TPaintBox)
private
FGridOptions : TGridOptions;
FFocusedX,FFocusedY : integer;
FOnFocusChanged: TNotifyEvent;
procedure CalculateSizeAndPosition;
procedure DrawCell(X,Y : integer);
procedure DrawCells;
procedure SetGridOptions(const Value: TGridOptions);
protected
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X,Y: Integer); override;
public
constructor Create(aOwner : TComponent); override;
destructor Destroy; override;
procedure Paint; override;
procedure SetFocus(X,Y : integer);
published
property OnFocusChanged : TNotifyEvent read FOnFocusChanged write FOnFocusChanged;
property Options : TGridOptions read FGridOptions write SetGridOptions;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples',[TGridPaintBox]);
end;
procedure TGridPaintBox.CalculateSizeAndPosition;
begin
<...>
end;
constructor TGridPaintBox.Create(aOwner: TComponent);
begin
inherited;
FGridOptions := TGridOptions.Create(self);
end;
procedure TGridPaintBox.DrawCell(X,Y: integer);
begin
<...>
end;
procedure TGridPaintBox.DrawCells;
var
X,Y : integer;
begin
CalculateSizeAndPosition;
for Y := 0 to FGridOptions.CellsY-1 do
for X := 0 to FGridOptions.CellsX-1 do
DrawCell(X,Y);
end;
procedure TGridPaintBox.Paint;
begin
Canvas.Font := Font;
Canvas.Brush.Color := Color;
Canvas.Brush.Style := bsSolid;
Canvas.FillRect(Rect(0,Width,Height));
DrawCells;
if Assigned(OnPaint) then
OnPaint(Self);
end;
procedure TGridPaintBox.SetGridOptions(const Value: TGridOptions);
begin
FGridOptions.Assign(Value);
invalidate;
end;
procedure TGridPaintBox.MouseDown(Button: TMouseButton; Shift: TShiftState; X,Y: Integer);
begin
SetFocus(PixelToCellX(X),PixelToCellY(Y));
inherited;
end;
procedure TGridPaintBox.SetFocus(X,Y: integer);
begin
if (FocusedX=X) and (FocusedY=Y) then
exit;
FFocusedX := X;
FFocusedY := Y;
if assigned(OnFocusChanged) then
OnFocusChanged(self);
invalidate;
end;
constructor TGridOptions.Create(aGridPaintBox : TGridPaintBox);
begin
FCellsX := 20;
FCellsY := 8;
FDrawOptions := [gdoSquareCells,gdoDrawCellEdges];
end;
procedure TGridOptions.Assign(Source : TPersistent);
begin
if Source is TGridOptions then
begin
FCellsX := TGridOptions(Source).CellsX;
FCellsY := TGridOptions(Source).CellsY;
FDrawOptions := TGridOptions(Source).DrawOptions;
end
else
inherited;
end;
end.
解决方法
这是因为您没有一个选项集的setter,这将使您的控件属于无效.表单设计器中的点击调用控件无效,但是您应该在这样的选项设置器中由您自己处理.所以我会存储选项所有者更好地访问直接的所有者类实例,并在选项设置器强制这个所有者,控件重绘:
type
TGridPaintBox = class;
TGridDrawOption = (gdoSquareCells,gdoDrawFocus);
TGridDrawOptions = set of TGridDrawOption;
TGridOptions = class(TPersistent)
private
FOwner: TGridPaintBox;
FCellsX: Integer;
FCellsY: Integer;
FDrawOptions: TGridDrawOptions;
procedure SetCellsX(AValue: Integer);
procedure SetCellsY(AValue: Integer);
procedure SetDrawOptions(const AValue: TGridDrawOptions);
public
constructor Create(AOwner: TGridPaintBox);
procedure Assign(ASource: TPersistent); override;
published
property CellsX: Integer read FCellsX write SetCellsX;
property CellsY: Integer read FCellsY write SetCellsY;
property DrawOptions: TGridDrawOptions read FDrawOptions write SetDrawOptions;
end;
implementation
constructor TGridOptions.Create(AOwner: TGridPaintBox);
begin
FOwner := AOwner;
FCellsX := 20;
FCellsY := 8;
FDrawOptions := [gdoSquareCells,gdoDrawCellEdges];
end;
procedure TGridOptions.SetCellsX(AValue: Integer);
begin
if FCellsX <> AValue then
begin
FCellsX := AValue;
FOwner.Invalidate;
end;
end;
procedure TGridOptions.SetCellsY(AValue: Integer);
begin
if FCellsY <> AValue then
begin
FCellsY := AValue;
FOwner.Invalidate;
end;
end;
procedure TGridOptions.SetDrawOptions(const AValue: TGridDrawOptions);
begin
if FDrawOptions <> AValue then
begin
FDrawOptions := AValue;
FOwner.Invalidate;
end;
end;
进一步说明: 如果您不明确需要绘制框的发布属性和事件,例如Color,Font或OnPaint事件,则从TGraphicControl而不是TPaintBox导出控件.您可以选择自己发布的属性和事件. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
