Ich habe eine Komponente, TGridPaintBox, basierend auf TPaintBox erstellt. Es ist im Grunde ein Paintbox mit "Grid-Funktionalität" hinzugefügt. Es ist kein Datenraster. Mehr wie eine Schachbrettkomponente.Warum wird meine benutzerdefinierte Komponente nicht aktualisiert, wenn ich Eigenschaften ändere?
Im Objekt-Explorer kann ich bestimmte Eigenschaften festlegen. Am wichtigsten ist, dass ich die Rastermaße festlegen kann (wie viele Zellen über/unter), aber auch Optionen bezüglich des Zeichnens. Ob die Zellen quadratisch sein sollten, die Farbe von ungeraden/geraden Zellen usw.
Meine erste Version dieser Komponente hatte Eigenschaften direkt auf der Klasse, und wenn ich eine Eigenschaft änderte, wurde die Zeichnungszeitzeichnung sofort aktualisiert. Als die Komponente wuchs, wollte ich meine Eigenschaften ein wenig besser organisieren und führte einige "Optioneneigenschaften" ein, wie Zeichenoptionen, Verhaltensoptionen usw. Nach dieser Einführung wird die Zeichnungszeitzeichnung nicht mehr wie zuvor aktualisiert. Nach dem Ändern einer Eigenschaft muss ich auf die Komponente klicken, um sie zu aktualisieren. Kann mir jemand sagen, warum das passiert?
Hier ist eine abgespeckte Version des Codes. Ich hoffe, es wird das Verhalten erklären:
(PS: Dies ist meine erste Komponente, obwohl ich Delphi seit 1997 verwendet habe, also wenn jemand etwas dummes in der Art finde ich habe es getan, bitte fühlen frei, mir zu sagen)
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.
Ja, Tippfehler. Es ist tatsächlich in der TGridPaintBox-Klasse, aber ich habe beim Bearbeiten für diesen Beitrag versagt. Ich werde meine Frage aktualisieren. –
Danke auch für den Tipp über TGraphicControl statt TPaintBox. Und natürlich, danke für den Rest der Antwort. Es hat mein Problem gelöst :-) –