Почему мой пользовательский компонент не обновляется, когда я изменяю свойства?

Я создал компонент TGridPaintBox на основе TPaintBox. По сути, это коробка для рисования с добавленной «функцией сетки». Это не сетка данных. Больше похоже на элемент шахматной доски.

В проводнике объектов я могу установить определенные свойства. Самое главное, я могу установить размеры сетки (сколько ячеек поперек/вниз), а также параметры, относящиеся к рисованию. Должны ли ячейки быть квадратными, цвет нечетных/четных ячеек и т. д.

Моя первая версия этого компонента имела свойства непосредственно в классе, и когда я изменил свойство, чертеж во время разработки немедленно обновлялся. По мере роста компонента я хотел немного лучше организовать свои свойства и ввел некоторые «свойства параметров», такие как параметры рисования, параметры поведения и т. д. После этого рисунок во время разработки больше не обновляется, как раньше. После изменения свойства мне нужно щелкнуть компонент, чтобы он обновился. Может ли кто-нибудь сказать мне, почему это происходит?

Вот урезанная версия кода. Я надеюсь, что это объяснит поведение:

(PS: это мой первый компонент, хотя я использую Delphi с 1997 года, поэтому, если кто-нибудь заметит какую-нибудь глупость в том, как я это сделал, пожалуйста, не стесняйтесь сказать мне)

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,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,gdoCenterCells,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.
12
задан Svein Bringsli 13 June 2012 в 08:30
поделиться