2012-06-10 35 views
12

TPaintBox'a dayanan bir bileşen, TGridPaintBox oluşturdum. Temel olarak "grid işlevselliği" eklenmiş bir paintbox. Veri şebekesi değil. Daha çok bir satranç tahtası bileşeni gibi.Özellikleri değiştirdiğimde neden özel bileşenim güncellenmiyor?

Nesne Gezgini'nde bazı özellikleri ayarlayabilirim. En önemlisi, ızgara boyutlarını (kaç tane/daha fazla hücre), ayrıca çizim ile ilgili seçenekleri de ayarlayabilirim. Hücrelerin kare, tek/çift hücrelerin rengi vb. Olması gerekip gerekmediği

Bu bileşenin ilk sürümünün doğrudan sınıfta özellikleri vardı ve bir özelliği değiştirdiğimde, zamanlama çizimi hemen güncelleştirildi. Bileşen büyüdükçe, özelliklerimi biraz daha iyi organize etmek istedim ve çizim seçenekleri, davranış seçenekleri vb. Gibi bazı "seçenekler özellikleri" ni tanıtmak istedim. Bir özelliği değiştirdikten sonra, güncellenmesi için bileşeni tıklamam gerekiyor. Bana bunun neden olduğunu söyleyen var mı?

Kodun soyulmuş bir sürümü aşağıdadır. Umarım davranışları açıklar:

(PS: Bu benim ilk bileşenim, 1997'den beri Delphi kullanmış olmama rağmen, eğer herkes benim yaptığım gibi aptalca bir şey fark ederse, lütfen Eğer aittir kontrolünüzü geçersiz hangi set seçenekleri için bir ayarlayıcı yok diye bir şey yok

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. 

cevap

13

) söyle ücretsiz. Form tasarımcısındaki tıklama, kontrolü geçersiz kılmak için çağrıda bulunur, ancak bu seçenek ayarlayıcıda kendi başınıza halletmeniz gerekir. Bu yüzden doğrudan sahibi sınıf örneğine ve seçenekler bu sahibini zorlamak ayarlayıcı daha iyi erişim için seçenekler sahibini saklamak istiyorum, kontrolü yeniden çizmek için:

type 
    TGridPaintBox = class; 
    TGridDrawOption = (gdoSquareCells, gdoCenterCells, gdoDrawCellEdges, gdoDrawFocus); 
    TGridDrawOptions = set of TGridDrawOption; 
    TGridOptions = class(TPersistent) 
    private 
    FOwner: TGridPaintBox; 
    FCellsX: Integer; 
    FCellsY: Integer; 
    FDrawOptions: TGridDrawOptions; 
    procedure SetCellsX(AValue: Integer); 
    procedure SetCellsY(AValue: Integer); 
    procedure SetDrawOptions(const AValue: TGridDrawOptions); 
    public 
    constructor Create(AOwner: TGridPaintBox); 
    procedure Assign(ASource: TPersistent); override; 
    published 
    property CellsX: Integer read FCellsX write SetCellsX; 
    property CellsY: Integer read FCellsY write SetCellsY; 
    property DrawOptions: TGridDrawOptions read FDrawOptions write SetDrawOptions; 
    end; 

implementation 

constructor TGridOptions.Create(AOwner: TGridPaintBox); 
begin 
    FOwner := AOwner; 
    FCellsX := 20; 
    FCellsY := 8; 
    FDrawOptions := [gdoSquareCells, gdoCenterCells, gdoDrawCellEdges]; 
end; 

procedure TGridOptions.SetCellsX(AValue: Integer); 
begin 
    if FCellsX <> AValue then 
    begin 
    FCellsX := AValue; 
    FOwner.Invalidate; 
    end; 
end; 

procedure TGridOptions.SetCellsY(AValue: Integer); 
begin 
    if FCellsY <> AValue then 
    begin 
    FCellsY := AValue; 
    FOwner.Invalidate; 
    end; 
end; 

procedure TGridOptions.SetDrawOptions(const AValue: TGridDrawOptions); 
begin 
    if FDrawOptions <> AValue then 
    begin 
    FDrawOptions := AValue; 
    FOwner.Invalidate; 
    end; 
end; 

Daha notlar:

Eğer Color, Font veya OnPaint olayı gibi yayınlanmış özellikleri ve olayları açıkça belirtmeniz gerekmez, denetiminiziyerine TGraphicControl'dan alın. Hangi özellikleri ve etkinlikleri kendi başınıza yayınlayacağınızı seçebilirsiniz.

+1

Evet, yazım hatası. Bu aslında TGridPaintBox sınıfında, ancak bu yazı için düzenleme yaparken berbat ettim. Sorumu güncelleyeceğim. –

+1

Ayrıca, TPaintBox yerine TGraphicControl türetme hakkında ipucu için teşekkürler. Ve tabi ki, cevabın geri kalanı için teşekkürler. Sorunumu çözdü :-) –