![]() |
Abgel. graf. Komponente aktualisiert nicht
Servus Leute,
nach längerer Zeit habe ich mich dann nun auch endlich mal wieder ans Programmieren rangewagt und stehe sofort vor einem - eher kleinen, aber dennoch nervigen - Problem. Ich versuche gerade, ein Kartenspiel zu programmieren und habe mir für diesen Zweck eine Klasse TCustomCard von TGraphicControl abgeleitet, von der ich wiederrum die 3 verschiedenen Kartentypen (Karten mit Zahlen von 1-12 in 4 Farben, Joker, Aussetzen) ableite. Die Basisklasse besitzt so gut wie keine Eigenschaften und Funktionen, insofern hätte ich das ganze auch anders lösen können. Ich empfand es aber als gute Möglichkeit, mal den Umgang mit Vererbung etwas näher kennen zu lernen. Die Basisklasse besitzt die Eigenschaft CardOpen : Boolean, die besagt, ob die Karte offen oder verdeckt liegt. Meine zugehörige setter-Methode sieht aus wie folgt:
Delphi-Quellcode:
Die Paint-Methode habe ich erst in den abgeleiteten Klassen implementiert, weil erst dort Daten vorhanden sind, über die ich die Oberfläche bestimme. Dennoch sollte doch - meinem Verständnis der Vererbung nach - bei einem Ändern der Eigenschaft in einer abgeleiteten Klasse auch die entsprechende Paint-Methode der abgeleiteten Klasse aufgerufen werden, und nicht die der Basisklasse, oder? Das scheint nämlich hier nicht der Fall zu sein. Die Oberfläche wird nämlich nicht neu gezeichnet. Erst durch eine Extra-Funktion in der abgeleiteten Klasse aktualisiert sich die Ansicht. :(
procedure TCustomCard.setCardOpen(aCardOpen : Boolean);
Begin if aCardOpen <> fCardOpen Then Begin fCardOpen := aCardOpen; Paint; End; End; Und ne kleine zweite Frage hätte ich auch noch kurz. Ich weiß, "neue Frage, neuer Thread", aber die Frage is eigentlich so klein, daß sich ein Thread nicht lohnt. ;) Kann ich - der Einfachheit halber - diese abgeleiteten Klassen später dennoch als TCustomCard deklarieren, und dann per Typenüberprüfung darauf zugreifen? Das könnte mir später eventuell etwas Arbeit ersparen. |
Re: Abgel. graf. Komponente aktualisiert nicht
zu 2.: Ja, kannst du, das nennt sich Polymorphie
zu 1.: Wie ist TCustomCard.Paint deklariert? Empfehlenswert wäre
Delphi-Quellcode:
procedure Paint; virtual; abstract;
|
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
Zitat:
|
Re: Abgel. graf. Komponente aktualisiert nicht
Delphi-Quellcode:
type TBase = class
protected procedure Paint; virtual; abstract; public procedure DoSomething; end;
Delphi-Quellcode:
Wenn du in einer Mehtode in Base nun Paint aufrufst wird die Implementierung der Ableitung benutzt.
type
Descendant1 = class(Base) protected procedure Paint; override; end; Descendant2 = class(Base) protected procedure Paint; override; end; Zur Frage nach der Polymorphy:
Delphi-Quellcode:
Instance1 & Instance2 lassen sich somit auf die Methoden von Base zusammenfassen und gleich behandeln, sie zeichnen sich aber unterschiedlich. ;)
var
Instance1, Instance2 :Base; begin Instance1 := Descendant1.Create(); Instance2 := Descendant2.Create(); |
Re: Abgel. graf. Komponente aktualisiert nicht
OK, danke für die erklärende Zusammenfassung. Werd ich mir zu Gemüte führen und später dann mal testen. Und dann mal schaun, wie weit ich komme, wenn ich damit dann die einzelnen Karten fertig hab. Jetzt fängts nämlich erst so richtig an :lol:
|
Re: Abgel. graf. Komponente aktualisiert nicht
Mist, jetzt sehe ich gerade, daß Robert noch override hinter die Paint-Methoden der abgeleiteten Klassen gepackt hat. :wall:
Ich meine aber, daß das bei mir nicht ging. Am Anfang müsste es nämlich so gewesen sein, weil ich vergessen hatte, es rauszunehmen, als ich virtual und abstract hinzugefügt hatte. Das ging aber, soweit ich mich erinnere nicht, weil die Paint-Methode in der Basisklasse nicht implementiert war. Habe ich sie dann implementiert, krieg ich einen Abstract Error. Klar, kann ja nich ne abstrakte Methode doch noch implementieren. So, dann hab ich das override und die Implementierung in der Basisklasse rausgenommen. Dann wurde auch brav compiliert. Beim Setzen von CardOpen (ihr erinnert euch, die setter-Methode aus meinem ersten Beitrag ;)) bekomme ich allerdings wieder einen Abstract Error. Warum? OK, davon jetzt mal abgesehen. Seit dem Ändern habe ich noch ein ganz anderes Problem bekommen: Die Paint-Methoden der abgeleiteten Klassen funktioniert nicht mehr richtig, seit ich das "inherited Paint" entfernt habe, daß mir ja nur Fehler gebracht hat, seit ich Paint als abstract deklariert hatte. Jetzt wird nämlich nicht neugezeichnet, wenn ich Paint aufrufe, es sei denn, ich rufe in der Paint-Methode zB als erstes ein ShowMessage auf. Kann mir das mal jemand erklären? :gruebel: //Edit: Ich pack jetzt einfach mal den relevanten Teil meines bisherigen Quellcodes rein, dann is es vielleicht einfacher, mir das näher zu bringen ;)
Delphi-Quellcode:
unit UCard;
interface uses SysUtils, Classes, Controls, Graphics; type TCardValue = (CVblue_01, CVblue_02, CVblue_03, CVblue_04, CVblue_05, CVblue_06, CVblue_07, CVblue_08, CVblue_09, CVblue_10, CVblue_11, CVblue_12, CVyellow_01, CVyellow_02, CVyellow_03, CVyellow_04, CVyellow_05, CVyellow_06, CVyellow_07, CVyellow_08, CVyellow_09, CVyellow_10, CVyellow_11, CVyellow_12, CVgreen_01, CVgreen_02, CVgreen_03, CVgreen_04, CVgreen_05, CVgreen_06, CVgreen_07, CVgreen_08, CVgreen_09, CVgreen_10, CVgreen_11, CVgreen_12, CVred_01, CVred_02, CVred_03, CVred_04, CVred_05, CVred_06, CVred_07, CVred_08, CVred_09, CVred_10, CVred_11, CVred_12); type TCustomCard = class(TGraphicControl) private { Private declarations } fCardOpen : Boolean; fImageDirectory, fCardImagePath : String; fCardImage : TBitmap; const CardFileNames : Array[0..50] of String = ('blue_01.bmp','blue_02.bmp','blue_03.bmp','blue_04.bmp','blue_05.bmp','blue_06.bmp', 'blue_07.bmp','blue_08.bmp','blue_09.bmp','blue_10.bmp','blue_11.bmp','blue_12.bmp', 'yellow_01.bmp','yellow_02.bmp','yellow_03.bmp','yellow_04.bmp','yellow_05.bmp','yellow_06.bmp', 'yellow_07.bmp','yellow_08.bmp','yellow_09.bmp','yellow_10.bmp','yellow_11.bmp','yellow_12.bmp', 'green_01.bmp','green_02.bmp','green_03.bmp','green_04.bmp','green_05.bmp','green_06.bmp', 'green_07.bmp','green_08.bmp','green_09.bmp','green_10.bmp','green_11.bmp','green_12.bmp', 'red_01.bmp','red_02.bmp','red_03.bmp','red_04.bmp','red_05.bmp','red_06.bmp', 'red_07.bmp','red_08.bmp','red_09.bmp','red_10.bmp','red_11.bmp.bmp','red_12.bmp', 'joker.bmp','next_player.bmp','backside.bmp'); procedure setCardOpen(aCardOpen : Boolean); protected { Protected declarations } procedure Paint; virtual; abstract; public { Public declarations } property CardOpen : Boolean read fCardOpen write setCardOpen; property ImageDirectory : String read fImageDirectory; constructor Create(aOwner : TComponent); override; destructor Destroy; override; published { Published declarations } end; type TCard = class(TCustomCard) private { Private declarations } fCardValue : TCardValue; protected { Protected declarations } procedure Paint; public { Public declarations } property CardValue : TCardValue read fCardValue; procedure Initialize(aImageDirectory : String; aCardValue : TCardValue; aCardOpen : Boolean = false); published { Published declarations } end; implementation { ******************************************************************************** ***********************************CUSTOMCARD*********************************** ******************************************************************************** } procedure TCustomCard.setCardOpen(aCardOpen : Boolean); Begin if aCardOpen <> fCardOpen Then Begin fCardOpen := aCardOpen; Paint; End; End; constructor TCustomCard.Create(aOwner : TComponent); Begin inherited Create(aOwner); Width := 57; Height := 86; fCardImage := TBitmap.Create; End; destructor TCustomCard.Destroy; Begin FreeAndNil(fCardImage); inherited Destroy; End; { ******************************************************************************** **************************************CARD************************************** ******************************************************************************** } procedure TCard.Paint; Begin fCardImage.LoadFromFile(fCardImagePath); Canvas.Draw(0,0,fCardImage); End; procedure TCard.Initialize(aImageDirectory : String; aCardValue : TCardValue; aCardOpen : Boolean = false); Begin If aImageDirectory <> fImageDirectory Then fImageDirectory := IncludeTrailingBackslash(aImageDIrectory); If aCardValue <> fCardValue Then fCardValue := aCardValue; If aCardOpen <> fCardOpen Then fCardOpen := aCardOpen; If fCardOpen Then fCardImagePath := fImageDirectory + CardFileNames[Integer(fCardValue)] Else fCardImagePath := fImageDirectory + CardFileNames[50]; Paint; End; |
Re: Abgel. graf. Komponente aktualisiert nicht
Du hast jetzt 2-mal Paint. Einmal von der Basisklasse und einmal von der Ableitung.
Wenn du eine abstrakte Methode überschreibst darfst du natürlich NICHT inherited aufrufen. Ist ja auch gar nix da, was im Vorgänger aufgerufen werden könnte -> *abstract error*. Wie kamst du eigentlich auf die Idee mit dem inherited? :gruebel: |
Re: Abgel. graf. Komponente aktualisiert nicht
Weil ich vorher eben keine abstrakte Basismethode hatte ;) Da war das inherited noch ein Überbleibsel. Allerdings hats ja - soweit ich mich erinnere - mit dem override auch nicht hingehauen, solange ich keine Paint-Methode in der Basisklasse implementiert hatte - da hat danna ber natürlich wieder das abstract zugehauen. ;)
Problem is aber grade, daß ich eben hier kein Delphi habe, und daher nur aus dem Gedächtnis erzählen kann. Vielleicht lieg ich auch irgendwo mal falsch. Könntest du mir gerade an meinem Code mal zeigen, wie ich das zum Laufen bekomme? |
Re: Abgel. graf. Komponente aktualisiert nicht
Also, so funktioniert es:
Delphi-Quellcode:
;)
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; TKlasse = class(TGraphicControl) public procedure DoSomething; end; TErbe1 = class(TKlasse) protected procedure Paint; override; end; TErbe2 = class(TKlasse) protected procedure Paint; override; end; var Form1: TForm1; Klasse: TKlasse; implementation {$R *.dfm} { TKlasse } procedure TKlasse.DoSomething; begin Paint; end; { TErbe1 } procedure TErbe1.Paint; begin inherited; with Canvas do begin Brush.Color := clRed; Rectangle(10, 10, 80, 80); end; end; { TErbe2 } procedure TErbe2.Paint; begin inherited; with Canvas do begin Brush.Color := clGreen; Ellipse(10, 10, 80, 80); end; end; procedure TForm1.FormCreate(Sender: TObject); begin Klasse := TErbe1.Create(Self); with Klasse do begin Parent := Self; Top := 50; Left := 50; Height := 100; Width := 100; end; end; procedure TForm1.Button1Click(Sender: TObject); begin Klasse.DoSomething; end; procedure TForm1.FormDestroy(Sender: TObject); begin Klasse.Free; end; end. |
Re: Abgel. graf. Komponente aktualisiert nicht
Also wenn das so funktioniert, dann möchte ich mal gerne wissen, was dann an meiner Setter-Methode so anders ist, daß es bei mir nicht funktioniert.
Naja, nichtsdestotrotz bin ich jetzt heiß darauf zu erfahren, wie ich es denn jetzt mit der abstrakten Methode zum Laufen bekomme. Sagt mal was... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:24 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz