Utworzono komponent, TGridPaintBox, oparty na TPaintBox. Jest to w zasadzie paintbox z dodaną "funkcjonalnością siatki". To nie jest siatka danych. Bardziej jak komponent szachownicy.Dlaczego mój składnik niestandardowy nie jest aktualizowany po zmianie właściwości?
W eksploratorze obiektów mogę ustawić określone właściwości. Co najważniejsze, mogę ustawić wymiary siatki (ile komórek w poprzek/w dół), ale także opcje związane z rysowaniem. Czy komórki mają być kwadratowe, kolor nieparzystych/równych komórek itd.
Moja pierwsza wersja tego komponentu miała właściwości bezpośrednio na klasie, a kiedy zmieniłem właściwość, rysunek designtime został natychmiast zaktualizowany. Wraz z rozwojem komponentu, chciałem trochę lepiej uporządkować moje właściwości i wprowadzić pewne "właściwości opcji", takie jak opcje rysowania, opcje zachowania itp. Po wprowadzeniu tego rysunku designtime nie jest już aktualizowany jak poprzednio. Po zmianie właściwości muszę kliknąć komponent, który ma zostać zaktualizowany. Czy ktoś może mi powiedzieć, dlaczego tak się dzieje?
Oto obnażona wersja kodu. Mam nadzieję, że to wytłumaczy zachowanie:
(PS: To jest mój pierwszy komponent, mimo że używam Delphi od 1997 roku, więc jeśli ktoś zauważy coś głupiego w sposób, w jaki to zrobiłem, proszę możesz mi powiedzieć)
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.
Tak, literówka. W rzeczywistości jest to klasa TGridPaintBox, ale pomieszałem podczas edycji tego wpisu. Zaktualizuję moje pytanie. –
Ponadto, dzięki za wskazówkę wynikającą z TGraphicControl zamiast z TPaintBox. I oczywiście dzięki za resztę odpowiedzi. To rozwiązało mój problem :-) –