Ho creato un componente, TGridPaintBox, basato su TPaintBox. È fondamentalmente un paintbox con "funzionalità di griglia" aggiunta. Non è una griglia di dati. Più simile a un componente della scacchiera.Perché il componente personalizzato non viene aggiornato quando cambio le proprietà?
Nell'esploratore di oggetti è possibile impostare determinate proprietà. Soprattutto, posso impostare le dimensioni della griglia (quante celle sono aperte/discese), ma anche le opzioni relative al disegno. Se le celle devono essere quadrate, il colore delle celle pari/dispari ecc.
La mia prima versione di questo componente aveva proprietà direttamente sulla classe, e quando ho cambiato una proprietà, il disegno è stato aggiornato immediatamente. Mentre il componente cresceva, volevo organizzare le mie proprietà un po 'meglio e ho introdotto alcune "proprietà di opzioni", come opzioni di disegno, opzioni di comportamento, ecc. Dopo averlo introdotto, il disegno non si aggiornava più come prima. Dopo aver modificato una proprietà, devo fare clic sul componente da aggiornare. Qualcuno può dirmi perché questo succede?
Ecco una versione ridotta del codice. Spero che spiegherà il comportamento:
(PS: Questo è il mio primo componente, anche se uso Delphi dal 1997, quindi se qualcuno può individuare qualcosa di stupido nel modo in cui l'ho fatto, per favore sentiti libero di dirmi)
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ì, errore di battitura. In realtà è nella classe TGridPaintBox, ma mi sono incasinato durante la modifica per questo post. Aggiornerò la mia domanda –
Inoltre, grazie per il suggerimento derivante da TGraphicControl piuttosto che da TPaintBox. E, naturalmente, grazie per il resto della risposta. Ha risolto il mio problema :-) –