![]() |
Frage zur Komponentenerstellung graphisch
Hallo,
wir sollen in der Schule graphische Komponenten erstellen ( z.B. Ellipse,Dreieck oder eine Linie). Diese wird indirekt von TGraphicControl abgeleitet ( eine Klasse ist noch dazwischen als Grundlage für unsere Objekte, die uns bereitgestellt wurde). Nun ist es mir auch gelungen , diese anzeigen zu lassen über eine kennt-beziehung. Ich habe also dem Constructor das Formular übergegeben auf dem gezeichnet werden soll. Mein Lehrer meinte aber das dies nicht nötig ist, ich verstehe bloß nicht warum. Außerdem besteht das nächste Ziel darin ein Ziehen der Komponente zu ermöglichen, durch die properties OnMouseDown etc. Dies will bei mir nicht funktionieren und mein Verdacht besteht darin, dass das Formular in irgendeiner Weise aufgrund der reinen Kennt beziehung nicht richtig mit der Komponente verbunden ist. Viel Text - > kurzer Sinn -> Mir würde vll. schon eine kleine graphische Komponente reichen, die ohne kennt beziehung angezeigt werden kann, damit ich dann mit den Maus Ereignissen weiterarbeiten kann. In hoffnung auf hilfreiche Antworten Thomas |
AW: Frage zur Komponentenerstellung graphisch
Kennt-Beziehung ist etwas seltsam ausgedrückt. Eine sichbare Komponente hat zwei derartige Beziehungen:
Den Owner (Besitzer) der im Create angegeben wird. Der ist nicht zwingend nötig, aber dieser Owner löscht das Objekt wenn er selbst beendet wird (meist die Application oder ein Formular) Das Parent (-Fenster), welches wichtig ist, damit die Komponente angezeigt werden kann. Wenn Dein Objekt angezeigt wird, dann sollte da aber der richtige Wert gesetzt sein. Zum ziehen mit der Mouse... soll das Objekt das von sich aus regeln oder soll es quasi von aussen über Objekt-Ereignisse gelöst werden? ...und wie immer... etwas Beispielcode, was Du schon versucht hast hilft manchmal. |
AW: Frage zur Komponentenerstellung graphisch
Also mit kennt-beziehung meinte ich, das das formular auf dem es erscheinen soll als parameter an den constructor übergeben werden soll.
Hier mal der Code der Componente
Delphi-Quellcode:
Der nächste schritt sollte sein über die Ereignisse MyMouseDown,Move und Up das Bewegen des Objektes zu realisieren. Allerdings reagiert es bis jetzt nicht wenn ich einfach drauf klicke.
unit GraphicControl1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, mGeoForm, StdCtrls; type toval = class(tgeoform) private public x1,x2,y1,y2:integer; zeichenflaeche:tform; constructor Create(f:Tform);reintroduce; procedure paint();override; procedure MyMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftstate;x,y : integer); override; procedure MyMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); override; procedure MyMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; override; end; implementation constructor toval.Create(f:Tform); begin //inherited create(self); x1:=50; y1:=50; x2:=150; y2:=100; zeichenflaeche:=f; OnMouseDown := MyMouseDown; OnMouseMove := MyMouseMove; OnMouseUp := MyMouseup; end; procedure toval.MyMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; begin // end; end; procedure toval.MyMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin end; procedure toval.MyMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; begin zeichenflaeche.Canvas.Ellipse(x1+40,y1+40,x2+40,y2+40); end; procedure toval.paint(); var vFuellfarbe,vRandfarbe : Tcolor; begin vFuellfarbe := self.Fuellfarbe; vRandfarbe := self.Randfarbe; zeichenflaeche.Canvas.Brush.Color := vFuellfarbe; zeichenflaeche.Canvas.Pen.Color := vRandfarbe; zeichenflaeche.Canvas.Pen.Width := 3; zeichenflaeche.Canvas.Ellipse(x1,y1,x2,y2); end; end. |
AW: Frage zur Komponentenerstellung graphisch
Hi Thomas,
also das wirkt alles etwas unausgegoren... Sofern TGeoForm bzw. im weiteren TOval von TGraphicControl abgeleitet ist, hat es ja einen eigenen Canvas, auf den Du zeichnen kannst (und solltest). Der geht von "0,0" bis "Width, Height" und in dem Bereich kannst Du zeichnen. Mit Oval.Parent := MyForm setzt Du es auf das Formular und mit Oval.Top und Oval.Left legst Du die Position auf dem Form fest. Wenn Du direkt auf das Formular zeichnest, sind dort zwar entsprechende Farben zu sehen, aber es ist dort ja kein Control, das auf Deine Mausereignisse reagieren kann. Zum Testen, ob bestimmte Stellen abgearbeitet werden bietet sich gern mal ein "Beep;" an, dann hat man schnell eine Rückmeldung. Oder natürlich auch Haltepunkte. Gruß Stahli |
AW: Frage zur Komponentenerstellung graphisch
Delphi-Quellcode:
procedure toval.MyMouseMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); begin FX := x; FY := Y; end; procedure toval.MyMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if ssLeft in Shift then begin x1 := x1 + X - FX; x2 := x2 + X - FX; y1 := y1 + Y - FY; y2 := y2 + Y - FY; FX := x; FY := Y; end; end; |
AW: Frage zur Komponentenerstellung graphisch
Genau das ist ja mein Problem. Ich möchte, dass das Objekt auf der Canvas gezeichnet wird, bloß gibt es da wohl probleme mit dem constructor.
Ich habe den jetzt mal so geschrieben, wie ich es mir vorstellen würde wie es ohne übergabe der Zeichenfläche funktionieren sollte (also vorher hat er es ja wenigstens gezeichnet, bloß ohne zugriff !? ). Allerdings wird alles zwar kompiliert,doch beim Klick auf den Button stürzt das Programm ab, ohne dass es die fehlerhaften Zeilen markiert :( Hier der neue Constructor:
Delphi-Quellcode:
der Constructor der Oberklasse TGeoform :
constructor toval.Create(AOwner:Tcomponent);
begin inherited create(self); x1:=50; y1:=50; x2:=150; y2:=100; end;
Delphi-Quellcode:
und der Befehl der beim Button Klick auf der Userform ausgeführt wird:
constructor TGeoForm.Create(AOwner: TComponent);
begin FFuellfarbe:=clWhite; FRandfarbe:=clBlack; Top:=0; Left:=0; Width:=100; Height:=50; OnMouseDown := MyMouseDown; OnMouseMove := MyMouseMove; OnMouseUp := MyMouseUp ; end;
Delphi-Quellcode:
hier evtl. noch die paint methode, falls es daran liegen könnte (jetzt ohne zeichenflaeche.canvas)
procedure TForm1.Button1Click(Sender: TObject);
begin oval:=toval.create(self); oval.Parent := Form1; oval.Fuellfarbe := Colorbox1.Selected; oval.Randfarbe := Colorbox2.Selected; oval.Paint; end;
Delphi-Quellcode:
Meine Frage ist halt, wie ich diesen Constructor oder dessen Aufruf genau schreiben muss, damit es dort nicht hakt :)
procedure toval.paint();
var vFuellfarbe,vRandfarbe : Tcolor; begin vFuellfarbe := self.Fuellfarbe; vRandfarbe := self.Randfarbe; Canvas.Brush.Color := vFuellfarbe; Canvas.Pen.Color := vRandfarbe; Canvas.Pen.Width := 3; Canvas.Ellipse(x1,y1,x2,y2); Edit: @ bummi: da lag erstmal gar nicht mein problem, ich brauche halt erstmal den schritt, dass das objekt überhaupt auf einen klick reagiert. vll. kennt da ja jemand noch einen guten test-aufruf, weil ich hier im forum gelesen hatte, dass bei eventhandlern showmessage nicht verwendet werden sollte gruß thomas |
AW: Frage zur Komponentenerstellung graphisch
Delphi-Quellcode:
Wenn Du
constructor toval.Create(AOwner:Tcomponent);
begin inherited;
Delphi-Quellcode:
.
inherited Create(self);
aufrufst, dann sagst Du deinem Objekt, ich gehöre mir selbst und in der Folge: Ich bin mein Vater ;) Nur inherited wird quasi ausgeführt wie
Delphi-Quellcode:
sofern die Create-Methode vom Vorgänger-Object identisch deklariert ist.
constructor toval.Create(AOwner:Tcomponent);
begin inherited Create(AOwner); |
AW: Frage zur Komponentenerstellung graphisch
Zitat:
Jetzt zeigt er mir aber immer noch beim klick auf den button das fenster mit der aufschrift cpu und den vielen daten an |
AW: Frage zur Komponentenerstellung graphisch
Poste doch nochmal den Code der TOval Klasse, wie er jetzt aussieht.
|
AW: Frage zur Komponentenerstellung graphisch
Also TGraphicControl kennt im Constructor kein OwnerControl.
Sicherlich ist Euer TGeoForm also von TCustomControl abgeleitet. Wo hast Du denn Dein Objekt "Oval" definiert? Ansonsten kann ich jetzt aus den zitierten Ausschnitten nichts erkennen, was zu einem Absturz führen solle... Meine Tipps: - struturiere Deinen Quelltext übersichtlicher, dann liest er sich besser und Fehler lassen sich eher finden - arbeite das Programm schrittweise ab (Haltepunkt + F7) - zeig mal den gesamten Quelltext... [Edit @Satty67]"Ich bin mein Vater" ... klar! Meine Ausrede: Ich bin Brillenträger ;-)[/Edit) |
AW: Frage zur Komponentenerstellung graphisch
Zitat:
..oder meist Du TControl <> TComponent, dann OK. Ist aber bei ihm als TComponent deklariert. |
AW: Frage zur Komponentenerstellung graphisch
Ok, ich poste hier nochmal den kompletten code des Ovals und der Oberklasse Tgeoform, die von Tgraphiccontrol abgeleitet ist
Delphi-Quellcode:
und hier der quellcode der oberklasse tgeoform
unit GraphicControl1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, mGeoForm, StdCtrls; type toval = class(tgeoform) private public x1,x2,y1,y2:integer; zeichenflaeche:tform; constructor Create(AOwner:Tcomponent);override; procedure paint();override; procedure MyMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftstate;x,y : integer); override; procedure MyMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); override; procedure MyMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; override; end; implementation constructor toval.Create(AOwner:Tcomponent); begin inherited ; x1:=50; y1:=50; x2:=150; y2:=100; //zeichenflaeche:=f; {OnMouseDown := MyMouseDown; OnMouseMove := MyMouseMove; OnMouseUp := MyMouseup; } end; procedure toval.MyMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; begin // end; end; procedure toval.MyMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin end; procedure toval.MyMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; begin Canvas.Ellipse(x1+40,y1+40,x2+40,y2+40); end; procedure toval.paint(); var vFuellfarbe,vRandfarbe : Tcolor; begin vFuellfarbe := self.Fuellfarbe; vRandfarbe := self.Randfarbe; Canvas.Brush.Color := vFuellfarbe; Canvas.Pen.Color := vRandfarbe; Canvas.Pen.Width := 3; Canvas.Ellipse(x1,y1,x2,y2); end; end.
Delphi-Quellcode:
und zum schluss der aufruf im formular ( da kann es ja nur, wenn überhaupt, an dem aufruf liegen)
unit mGeoForm;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TGeoForm = class(TGraphicControl) // Basis aller graphischen Komponenten ohne eigenes Fenster. // Sie kapselt ein Canvasobjekt und eine paint-Methode. private FRandfarbe: TColor; FFuellfarbe: TColor; procedure SetFuellfarbe(const Value: TColor); function GetFuellfarbe: TColor; procedure SetRandfarbe(const Value: TColor); function GetRandfarbe: TColor; protected procedure MyMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftstate;x,y : integer); virtual; procedure MyMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); virtual; procedure MyMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; virtual; const ZIEH_RECT_LAENGE = 10; procedure Paint; virtual; function PunktZiehen(Punkt: TPoint): Boolean; virtual; function PunktBewegen(Punkt: TPoint): Boolean; virtual; public x1,x2,y1,y2:integer; zeichenflaeche:tform; constructor Create(AOwner: TComponent);virtual; published property Fuellfarbe : TColor read GetFuellfarbe write SetFuellfarbe; property Randfarbe : TColor read GetRandfarbe write SetRandfarbe; property OnMouseDown ; property OnMouseMove; property OnMouseUp; end; procedure Register; // registrieren der Komponente implementation procedure Register; begin RegisterComponents('GeoForm', [TGeoForm]); // erster Parameter: Name des Registers der Componentenpalette, in das die Komponente eingefügt werden soll. // zweiter Parameter: Aufführen der Komponentenklassen, die registriert werden sollen. end; constructor TGeoForm.Create(AOwner: TComponent); begin FFuellfarbe:=clWhite; FRandfarbe:=clBlack; Top:=0; Left:=0; Width:=100; Height:=50; OnMouseDown := MyMouseDown; OnMouseMove := MyMouseMove; OnMouseUp := MyMouseUp ; end; function TGeoForm.GetFuellfarbe: TColor; begin result:= FFuellfarbe; end; function TGeoForm.GetRandfarbe: TColor; begin result:= FRandfarbe; end; procedure TGeoForm.Paint; begin inherited; end; function TGeoForm.PunktBewegen(Punkt: TPoint): Boolean; begin Result := True; end; function TGeoForm.PunktZiehen(Punkt: TPoint): Boolean; begin if (Punkt.X > Width -ZIEH_RECT_LAENGE) and (Punkt.X < Width) and (Punkt.Y > Height -ZIEH_RECT_LAENGE) and (Punkt.Y < Height) then Result := True else Result := False; end; {function TGeoForm.GetFuellfarbe : TColor; begin result := FFuellfarbe; end; } procedure TGeoForm.SetFuellfarbe(const Value: TColor); begin FFuellfarbe := Value; end; procedure TGeoForm.SetRandfarbe(const Value: TColor); begin FRandfarbe := Value; end; procedure tGeoform.MyMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; begin //ShowMessage('Hallo'); end; procedure tGeoform.MyMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin end; procedure tGeoform.MyMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ; begin end; end.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin oval:=toval.create(self); oval.Parent := Form1; oval.Fuellfarbe := Colorbox1.Selected; oval.Randfarbe := Colorbox2.Selected; oval.Paint; end; |
AW: Frage zur Komponentenerstellung graphisch
:oops: Ist gar nicht sooo frech!
Ich lege mich jetzt erst mal aufs Ohr ;-) |
AW: Frage zur Komponentenerstellung graphisch
Das ist von der Ferne etwas schwierig...
Sind die ColorBoxen instanziiert? Hast Du mal einen Haltepunkt in der ClickBehandlung gesetzt? Dann siehst Du doch, wie weit er kommt... |
AW: Frage zur Komponentenerstellung graphisch
Zitat:
Ich weiß nicht genau wie das mit den Haltepunkten funktionieren soll, da er es ja kompiliert und dann erst beim Klick der Fehler kommt. Habe trotzdem mal welche in die Click Prozedur gesetzt ( mit F5) aber da kommt der Error auch schon wenn der Haltepunkt beim Create gesetzt ist ( = Create ist das Problem ??) |
AW: Frage zur Komponentenerstellung graphisch
Delphi-Quellcode:
.
oval.Parent := Form1;
löst das Chaos aus, bin gerade noch am suchen... |
AW: Frage zur Komponentenerstellung graphisch
Aahh!
Delphi-Quellcode:
Hier fehlt das inherited.
constructor TGeoForm.Create(AOwner: TComponent);
begin FFuellfarbe:=clWhite; FRandfarbe:=clBlack; Top:=0; Left:=0; Width:=100; Height:=50; OnMouseDown := MyMouseDown; OnMouseMove := MyMouseMove; OnMouseUp := MyMouseUp ; end; Das Control wird nicht korrekt erzeugt. |
AW: Frage zur Komponentenerstellung graphisch
Zitat:
Kann das sein, dass man auf die canvas anders zugreifen muss als in meiner paint methode ?
Delphi-Quellcode:
procedure toval.paint();
var vFuellfarbe,vRandfarbe : Tcolor; begin vFuellfarbe := self.Fuellfarbe; vRandfarbe := self.Randfarbe; Canvas.Brush.Color := vFuellfarbe; Canvas.Pen.Color := vRandfarbe; Canvas.Pen.Width := 3; Canvas.Ellipse(x1,y1,x2,y2); end; |
AW: Frage zur Komponentenerstellung graphisch
Kann ich jetzt ad hoc nicht sagen.
Und was heißt "nicht richtig gezeichnet"? Ggf. teste Dich langsam heran. Z.B. erst mal Fillrect und eine Line zeichnen. |
AW: Frage zur Komponentenerstellung graphisch
Also momentan zeichnet er halt nichts, bzw. zeigt nichts an. Auch kein einfaches LineTo
Es wird wohl irgendwie daran liegen, dass nicht richtig klar gezeigt ist, wo gezeichnet werden soll. Ich dachte, das wäre durch
Delphi-Quellcode:
schon geschehen. Wenn also die Paint Methode aufgerufen, wird vll. eine andere Canvas benutzt, als die die auch angezeigt wird auf dem Formular, wie gesagt das weiß ich nicht genau.
oval.parent := Tform1
|
AW: Frage zur Komponentenerstellung graphisch
Besser, entferne aus der Basisklasse TGeoForm Paint komplett. (Also Deklaration Paint, virtual und die fast leere Methode, in der nur inherited steht)
Dann setze in TOval die Koordinaten in den sichtbaren Bereich:
Delphi-Quellcode:
Zum verschieben, verschiebst Du dann nicht das Oval in deiner Klasse, sondern die ganze Klasse durch ändern von Top und Left.
x1:=0;
y1:=0; x2:=Width; y2:=Height; *** Grundsätzliches: Dein Oval füllt Deine Komponente TOval ganz aus. Deshalb könnte man in TOval.Paint gleich
Delphi-Quellcode:
.
Canvas.Ellipse(0, 0, width, height);
Dann wird das Oval größer, wenn die Komponente größer wird. x1,x2,y1,y2 kann man sich dann ganz sparen! Verschoben wird dann wie gesagt nicht das Oval in der Komponente, sondern die ganze Komponente durch ändern von Top und Left. |
AW: Frage zur Komponentenerstellung graphisch
Delphi-Quellcode:
sollte doch etwas zeichnen.
with Canvas do
begin Brush.Color := clRed; FillRect(GetClientRect); Pen.Style := psSolid; Pen.Color := clBlue; Pen.Style := psDot; Rectangle(GetClientRect); end; Setze mal auch noch Oval.Left und Oval.Top. |
AW: Frage zur Komponentenerstellung graphisch
Liste der Anhänge anzeigen (Anzahl: 1)
Ich würde ja das sinnlose Paint aus der Basisklasse TGeoForm entfernen.
TOval.Paint braucht auch keine lokalen variablen, das kann ganz übersichtlich bleiben:
Delphi-Quellcode:
procedure TOval.Paint();
begin Canvas.Brush.Color := self.Fuellfarbe; Canvas.Pen.Color := self.Randfarbe; Canvas.Pen.Width := 3; Canvas.Ellipse(0, 0, width, height); end; Zitat:
|
AW: Frage zur Komponentenerstellung graphisch
Momentan will es ja noch gar nicht gezeichnet werden.
Ich verstehe jetzt bloß nicht warum ich das Paint aus der Klasse TGeoform entfernen soll ? Die Methode Paint ist ja nur abstrakt vorher und hat damit keinerlei Implementation meine ich. Habe das mit den Koordinaten mal in den Constructor geschrieben, will aber auch nicht klappen. Edit @ stahli will auch nicht klappen. das top und left ist ja im constructor von tgeoform gesetzt und wird beim inherited aufgerufen. Ich werde morgen in der schule mal konkret nachfragen und hier dann das Ergebnis posten, bin jetzt erstmal schlafen :) Aber schonmal vielen Dank für die ganze Hilfe, die mich schon ein ganzes stück weiter gebracht hat :) (bei anderen foren erlebt man es ja manchmal, dass neuen mitgliedern nicht so schnell geholfen wird oder einfach auf die tutorials verwiesen wird) |
AW: Frage zur Komponentenerstellung graphisch
Jo, und weil Sie in der Basisklasse ohne Funktion ist, dort unnötig. (Wenn Du es machst wird auch gezeichnet)
Wie Du am Bild (#23) siehst, fehlt nicht viel (#21) ;) Aber muss ja nicht heute alles klappen... |
AW: Frage zur Komponentenerstellung graphisch
Hallo nochmal,
nachdem ich den Code jetzt nochmal sauber in neue Units geschrieben habe, klappt es :thumb: war wohl irgendwo wieder ein kleiner Fehler drin :? Aber vielen Dank für die Hilfe :) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:02 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 by Thomas Breitkreuz