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... |
Re: Abgel. graf. Komponente aktualisiert nicht
nooochmaaal zum Mitschreiben...
override klappt nur mit Methoden, die als virtual oder dynamic deklariert sind. Eine abstrakte Methode ist virtuell, aber sie enthält keine Implementierung. (Ich habe absolut KEINE Ahnung, warum man das virtual davor schreiben muss :wall: ) Wenn du für verschiedene Ableitungen unetrschiedliches Verhalten haben willst, dass du auf einen gleichen Satz von Methoden/PRoperties zusammenfassen kannst *musst* du virtuelle Methoden nehmen.
Delphi-Quellcode:
du hattest:
Base = class
procedure Paint; virtual; abstract; procedure DoSomething; end;
Delphi-Quellcode:
Was ist falsch?
Descendant = class(Base)
procedure Paint; end; Du hast eine neue Methode Namens Paint eingeführt, anstatt Base.Paint zu implementieren.
Delphi-Quellcode:
Das sind zwei unterschiedliche Methoden, Erstere gibt dir den abstract error, da sie nix hat, was sie ausführen könnte.
var
Instance : Descendant; begin Instance.Paint(); Base(Instance).Paint(); Bist du innerhalb von Base greifst du also auf die Methode zu, von der du verlangst, dass sie der Nachfolger implementiert:
Delphi-Quellcode:
Sollte also klar sein warum es knallt. ;)
procedure Base.DoSomething;
begin Paint(); end; Zweiter Fehler, den du vllt gemacht hast:
Delphi-Quellcode:
Damit zwingst du einen Call direkt auf die abstrakte Methode von Base -> *boom* :)
procedure Descendant.Paint;
begin inherited; Also kurz und knapp: a) überschreibe die Methode b) kein inherited (ist ja sowieso nix zum Aufrufen da ;) ) btw: Du willst nicht wirklich bei jedem Zeichnen das Bild von der HDD laden, oder? :shock: |
Re: Abgel. graf. Komponente aktualisiert nicht
Wir haben in diesem Fall aber bereits eine virtuelle, nicht abstrakte Methode Paint des Basistyps TGraphicControl, um die wir uns in unserer Basisklasse (TKlasse/TBase/TCustomCard) gar nicht kümmern (müssen), da wir das unseren Nachfolgern überlassen.
Wenn wir nun eine Instanz der Basisklasse erzeigen, greift diese auf TGraphicCotrol.Paint zu, die nichts tut. Wenn wir in einem Nachfolger von der Basisklasse (TKlasse/TBase/TCustomCard) die paint-Methode überschreiben, dann wird auch in DoSomething (in Basisklasse (TKlasse/TBase/TCustomCard) implementiert; ruft Paint auf) die Paint-Methode des Nachfolgers aufgerufen. Alles Klar ? @_G also nix mit abstrakt & Co ;-) |
Re: Abgel. graf. Komponente aktualisiert nicht
Jungs, ihr 2 verwirrt mich gerade konkret. :stupid:
Abstrakt oder nicht abstrakt, das ist hier die Frage. :mrgreen: Um das jetzt nochmal zusammenzufassen: Ich deklariere Paint in der Basisklasse als abstract und virtual, implementiere sie aber nicht. Dann deklariere ich in den jeweiligen Nachkommen Paint mit override, rufe aber nicht inherited auf (klar, es gibt ja keine inherited Paint) Nun sollte auch in den Methoden der Basisklasse bei einem Aufruf von Paint die implementierte Paint des jeweiligen Nachfolgers aufgerufen werden. Stimmt das soweit? Dann werde ich das heute abend mal austesten (Vorsichtshalber, damit ich nichts vergesse, druck ich mir das Topic mal aus :stupid:) und mich dazu morgen nochmal äußern. Falls euch ncoh ne Ergänzung dazu einfällt, meldet euch bis dreiviertel 5, ansonsten bin ich nämlich schon wech. :mrgreen: Zitat:
|
Re: Abgel. graf. Komponente aktualisiert nicht
OK, danke für die Hilfe, das funktioniert jetzt wirklich. Da muß ich wohl gestern noch irgendnen Mist reingebaut haben!
|
Re: Abgel. graf. Komponente aktualisiert nicht
Delphi-Quellcode:
Man ruft nicht Paint sondern Invalidate.
procedure TCustomCard.setCardOpen(aCardOpen : Boolean);
Begin if aCardOpen <> fCardOpen Then Begin fCardOpen := aCardOpen; Invalidate; End; End; Invalidate markiert das Fenster als zum Neumalen vorgesehen. Windows loest daher eine WM_PAINT Nachricht aus. Das resultiert letztlich in einem Paint-Aufruf. Der Vorteil ist, das Windows mehrere Invalidates zusammenfasst und nur ein WM_PAINT schickt. Das bringt Speed. setCardOpen optimiert ja schon das nur bei der Aenderung der Property ueberhaupt ein Neumalen ausgeloest wird. Bei komplizierteren Aenderungen, bei denen mehrere Properties sich gegenseitig aendern, resultiert das in nur einem Neuzeichnen der Komponente. |
Re: Abgel. graf. Komponente aktualisiert nicht
OK, auch ein guter Tip. Danke dafür. Wieder was gelernt. :mrgreen:
|
Re: Abgel. graf. Komponente aktualisiert nicht
:gruebel: Nur leider wird bei Invalidate nichts neu gezeichnet, während Paint wunderbar funktioniert...
|
Re: Abgel. graf. Komponente aktualisiert nicht
Dann macht du etwas falsch. Ohne aktuelle Sourcen ist das aber nicht zu beurteilen.
|
Re: Abgel. graf. Komponente aktualisiert nicht
Sieht im Großen und Ganzen genauso aus wie weiter oben, mit den empfohlenen Änderungen. Lasse ich in der Setter-Methode Paint stehen, klappt es. Ersetze ich Paint hier durch Invalidate, wird beim Umdrehen der Karte nicht neu gezeichnet.
|
Re: Abgel. graf. Komponente aktualisiert nicht
"procedure Paint; override;" sollte es sein. TGraphicControl hat ja bereits eine Paint-Methode, die ueberschrieben werden soll.
Ohne override wird die Ableitungsverbindung zu TGraphicControl unterbrochen. Bitte poste doch nochmal deinen Code, damit man ihn korrigieren und optimieren kann. |
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
|
Re: Abgel. graf. Komponente aktualisiert nicht
OK, beim Versuch, meinen vorherigen Code anzupassen, ist mir gerade eine Idee gekommen, woran es liegen könnte. Bisher lade ich das anzuzeigende Bild noch in Paint. Das wollte ich dann noch ändern, wenn der Rest funktioniert. In diesem Fall wird dann aber eben dadurch, daß das angezeigt Bild sich erst in Paint verändert natürlich auch keine Notwendigkeit erkannt, die Komponente neu zu zeichnen. Daran wirds wohl liegen. Ich teste das heute abend nochmal aus und melde mich morgen dazu nochmal.
Die Anpassungen, die du gerade noch angesprochen hast, wurden ja schon längst durch die vorherigen Posts geklärt. Das is also drin. Wird daher wohl wirklich das sein, was ich gerade geschrieben habe. |
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
TGraphicCotrol.Paint sieht etwa so aus:
Delphi-Quellcode:
Dürfte also nicht allzu viel ausmachen :mrgreen:
procedure TGraphicCotrol.Paint;
begin end; |
Re: Abgel. graf. Komponente aktualisiert nicht
Eben deshalb wird nichts angezeigt. Wenn man Invalidate aufruft, so ist das natuerlich das Invalidate von TGraphicControl.
Da Paint nicht ueberschrieben ist, wird natuerlich das Paint von TGraphicControl und nicht das neu deklarierte Paint aufgerufen. Eine virtuelle Methode wird als Zeiger in der VMT (Virtual Method Table) abgelegt. Dort steht fuer diese Komponente erst mal das Paint von TGraphicControl. Aufrufe von Paint gehen per Index in die VMT des Objekts. Ueberschreibt man Paint in der abgeleiteten Konponente (override), so wird der Eintrag in der VMT durch das neue Paint ersetzt. Damit ist eigentlich die ganze Vererbung erklaert. dynamic macht keinen Eintrag in die VMT, stattdessen wird eine Suche nach dem Namen eingesetzt. Das Ergebnis ist das gleiche. Man tauscht nur Suchzeit gegen Speicherplatzersparnis. |
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
Natürlich ist es das. Rate mal warum es das gibt? Genau, damit man generisch ein Neuzeichnen des GraphicControl-Nachfolgers auslösen kann, dieser es aber selbst implementieren kann. Versteckt man Paint, bleibt es leer und nix passiert wenn man Paint auf die Instanz nach einem Cast auf GraphicControl ausführt.
Delphi-Quellcode:
...ist dann plötzlich etwas anderes als...
TGraphicControl(x).Paint();
Delphi-Quellcode:
X.Paint();
|
Re: Abgel. graf. Komponente aktualisiert nicht
So, nix is. Selbst nachdem ich jetzt auch schon in der Setter-Methode das Bild gesetzt habe, wird durch Invalidate nichts nue gezeichnet. Paint funktioniert aber weiterhin wunderbar. :gruebel:
Hier mal der bisherige Code:
Delphi-Quellcode:
unit UCard;
interface uses SysUtils, Classes, Controls, Graphics, Dialogs; type TCardType = (CTcard, CTjoker, CTnext_player); 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); TJokerValue = (JVblue_01, JVblue_02, JVblue_03, JVblue_04, JVblue_05, JVblue_06, JVblue_07, JVblue_08, JVblue_09, JVblue_10, JVblue_11, JVblue_12, JVyellow_01, JVyellow_02, JVyellow_03, JVyellow_04, JVyellow_05, JVyellow_06, JVyellow_07, JVyellow_08, JVyellow_09, JVyellow_10, JVyellow_11, JVyellow_12, JVgreen_01, JVgreen_02, JVgreen_03, JVgreen_04, JVgreen_05, JVgreen_06, JVgreen_07, JVgreen_08, JVgreen_09, JVgreen_10, JVgreen_11, JVgreen_12, JVred_01, JVred_02, JVred_03, JVred_04, JVred_05, JVred_06, JVred_07, JVred_08, JVred_09, JVred_10, JVred_11, JVred_12, JVall); 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; procedure SetCardImage; 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; override; procedure SetCardImage; override; 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; SetCardImage; Invalidate; End; End; constructor TCustomCard.Create(aOwner : TComponent); Begin inherited Create(aOwner); Width := 57; Height := 86; fCardImage := TBitmap.Create; End; destructor TCustomCard.Destroy; Begin inherited Destroy; FreeAndNil(fCardImage); End; { ******************************************************************************** **************************************CARD************************************** ******************************************************************************** } procedure TCard.Paint; Begin Canvas.Draw(0,0,fCardImage); End; procedure TCard.SetCardImage; Begin If fCardOpen Then fCardImagePath := fImageDirectory + CardFileNames[Integer(fCardValue)] Else fCardImagePath := fImageDirectory + CardFileNames[50]; fCardImage.LoadFromFile(fCardImagePath); 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; SetCardImage; Invalidate; End; end. |
Re: Abgel. graf. Komponente aktualisiert nicht
Schmeiss "procedure Paint; virtual; abstract;" raus.
|
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
//EDIT: wo war die rote Box?!? |
Re: Abgel. graf. Komponente aktualisiert nicht
:gruebel: Wie jetzt? Wovon wird denn hier die ganze Zeit in dem Thread geredet? Mir wurde hier doch erst gesagt, ich solle das reinsetzen, damit ich jeden Nachfahren individuell zeichnen kann?
|
Re: Abgel. graf. Komponente aktualisiert nicht
Auszug aus Controls.pas:
Delphi-Quellcode:
Oben ist die Definition von TGraphicControl, und die hat schon eine virtuelle Methode Paint. Die musst du mit override überschreiben, aber nicht mit abstract neu definieren.
TGraphicControl = class(TControl)
private FCanvas: TCanvas; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; protected procedure Paint; virtual; //<-- HIER !!! property Canvas: TCanvas read FCanvas; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; Nachtrag: und das override natürlich nur in der Klasse wo du es überschreibst. |
Re: Abgel. graf. Komponente aktualisiert nicht
Aha, endlich sprechen hier mal echte Experten. Robert_G? 6, setzen :mrgreen:
Naja, das test ich dann nachher gleich mal aus. Wär ja schön, wenn das endlich funktioniert. |
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
Zitat:
|
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
Seit Seite eins predige ich, was passiert, wenn man eine ehemals virtuelle Methode neu definiert. Da du das angefangen hast um dich mit Polymorphie zu befassen wollte ich doch nicht überall ins Detail gehen. Manche "D'ho"s muss man sich einfach selbst an die Stirn hauen. ;) |
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
Zitat:
Zitat:
@jfheins: Sorry, aber Robert hat mir das leider vor dir angefangen zu erklären, und ich hatte ihm soweit vertraut, daß er mir keinen Mist erzählt. ;) @all: Danke, das funktioniert jetzt wunderbar :thumb: |
Re: Abgel. graf. Komponente aktualisiert nicht
Zitat:
Hätte ich dir am Anfang gesagt: "Hey überschreib' einfach das Paint von GraphicControl", hättest du doch in einem halben Jahr noch keine abstrakte methode deklariert und in einer Ableitung implementiert, right? ;) Ich hätte aber nicht gedacht, dass es sich über 3 Seiten hinziehen muss... :gruebel: |
Re: Abgel. graf. Komponente aktualisiert nicht
Passt scho, jetzt hab ichs ja kapiert. Nur wenn einem als Anfänger in so nem Thema halt was erzählt wird, dann glaubt man das :zwinker:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:05 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz