He creado un componente, TGridPaintBox, basado en TPaintBox. Básicamente es una caja de pinturas con "funcionalidad de cuadrícula" añadida. No es una cuadrícula de datos. Más como un componente de tablero de ajedrez.¿Por qué mi componente personalizado no se actualiza cuando cambio las propiedades?
En el explorador de objetos puedo establecer ciertas propiedades. Lo más importante es que puedo establecer las dimensiones de la cuadrícula (cuántas celdas cruzadas/descendentes), pero también las opciones relacionadas con el dibujo. Si las celdas deben ser cuadradas, el color de las celdas pares/impares, etc.
Mi primera versión de este componente tenía propiedades directamente en la clase, y cuando cambié una propiedad, el dibujo del tiempo designado se actualizó de inmediato. A medida que el componente creció, quise organizar mis propiedades un poco mejor, e introduje algunas "propiedades de opciones", como opciones de dibujo, opciones de comportamiento, etc. Después de presentar esto, el dibujo del tiempo designado ya no se actualiza como antes. Después de cambiar una propiedad, tengo que hacer clic en el componente para que se actualice. ¿Alguien puede decirme por qué sucede esto?
Aquí hay una versión simplificada del código. Espero que explique el comportamiento:
(PD: Este es mi primer componente, a pesar de que he estado usando Delphi desde 1997, así que si alguien puede detectar algo estúpido en la forma en que lo he hecho, por favor sienta libre de decirme)
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.
Sí, error tipográfico. En realidad está en la clase TGridPaintBox, pero cometí un error al editar esta publicación. Actualizaré mi pregunta. –
Además, gracias por la sugerencia sobre derivar de TGraphicControl en lugar de TPaintBox. Y, por supuesto, gracias por el resto de la respuesta. Resolvió mi problema :-) –