Entwickler-Ecke
Multimedia / Grafik - Auf Klassenfremdes Canvas zugereifen
FinnO - Do 12.03.09 19:19
Titel: Auf Klassenfremdes Canvas zugereifen
Hi Community,
Im Informatikunterricht programmieren ein Kumpel und ich gerade eine neue, für unsere Zwecke verbesserte Turtle-Komponente.
Dazu würden wir gerne das Canvas, auf das gezeichnet werden soll variabel machen. Leider hagelt es bei ungefähr folgendem Code dauernd Zugriffsverletzungen
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| ... property ZielCanvas : TCanvas read GetCanvas write Setcanvas; ... begin ZielCanvas := Image.Canvas; end;
begin ZielCanvas.doSth end; |
muss man das evtl. Anders angehen?
Christian S. - Do 12.03.09 19:55
Ich fürchte, Hilfe wird hier schwer fallen. Du hast nicht gesagt, welche Fehler gemeldet werden und der Quelltext erscheint völlig aus dem Zusammenhang gerissen und entscheidende Teile (z.B. Getter- und Setter-Methoden) fehlen.
ub60 - Do 12.03.09 20:08
Bei dem geringen Quelltext nur eine Vermutung.
Also zuerst einmal, man kann´die Canvas zuweisen. Irgendwie sollte es dann aber
oder so heißen, Du übergibst ja nicht das Image.
ub60
FinnO - Do 12.03.09 21:59
Sorry, ich kann den Code aus der Schule leider nicht mehr wortwörtlich aber im Groben ist das so aufgebaut:
ich glaube, das canvas war eine Field...
Delphi-Quelltext
1:
| FZielCanvas : TCanvas; |
Gesetzt wird das ganze so:
Delphi-Quelltext
1:
| FZielCanvas := Image1.Canvas |
Die Idee dahinter ist, dass nun die Änderungen die wir an der ZielCanvas vornehmen sich auf die Image1.Canvas auswirken.
(ich glaube hier haben wir einen Denkfehler gemacht, muss man da mit Pointern o.ä. Arbeiten? Oder mit Handles (KP), weil ich glaube, so wie es momentan ist, werden die Änderungen nur in der ZielCanvas geändert nicht aber auf der eigentlich zu benutzenden Canvas Image1.Canvas?)
der Versuch zu Zeichnen ist dann
Delphi-Quelltext
1:
| FZielCanvas.LineTo(X,Y); |
und so weiter.
Yogu - Do 12.03.09 22:07
FinnO hat folgendes geschrieben : |
Delphi-Quelltext 1:
| FZielCanvas := Image1.Canvas | |
Was ist
Image1? Wo wird das gesetzt? Und warum glaubst du, dass die Änderungen an
FZielCanvas durchgeführt werden? Ein Canvas alleine ist nichts - du kannst ihn nicht einfach erzeugen, also muss er wohl der zugewiesene sein. Andernfalls würde eine Exception ausgelöst werden.
FinnO - Do 12.03.09 22:12
image1 ist eine ganz normale Komponente vom Typ TImage auf dem Formular...
Ich habe mittlerweile die Vermutung wir liegen sowas von falsch, dass ich lieber einfach mal unseren Code vergesse und die Frage in den Raum werf:
Angenommen, ich möchte ein beliebiges Bild auf irgendein beliebiges Canvas zeichnen, wie gehe ich das an? Dabei muss beachtet werden, dass ich Das Canvas variable zuweisen möchte und nicht Hardcoden.
Xentar - Do 12.03.09 22:45
Ähm.. versteh ich das richtig:
Du hast eine Klasse erstellt. In dieser Klasse möchtest du ein Canvas verwenden?
Warum greifst du dann doch wieder auf ein bestimmtes Canvas, nämlich in diesem Fall Image1.Canvas zu..?
Normalerweise geht man doch so vor, dass man beim instanziieren dieser Klasse das Canvas VON AUSSEN reinreicht, und nicht, dass sich die Klasse das selber holt?
Edit: Dafür ist ja normalerweise auch das Property, dass du bereits angelegt hast.. zeig mal mehr Code.
ub60 - Do 12.03.09 23:39
FinnO hat folgendes geschrieben : |
Die Idee dahinter ist, dass nun die Änderungen die wir an der ZielCanvas vornehmen sich auf die Image1.Canvas auswirken.
(ich glaube hier haben wir einen Denkfehler gemacht, muss man da mit Pointern o.ä. Arbeiten? |
Weder noch. Die Idee ist i.O., die übergebene Canvas ist nichts anderes als ein Zeiger.
Zum Vorgehen ein Beispiel:
- Ich möchte eine Figur als Klasse erstellen, deren Objekte man auf jeder Canvas zeichnen kann.
- Also erstelle ich in der Klasse ein Attribut FCanvas. Auf dieser Canvas führe ich alle Zeichenoperationen durch.
- Mit einer SetCanvas-Methode teile ich meinem Objekt (vor dem ersten Zeichnen) mit, auf welcher Canvas es gezeichnet werden soll.
ub60
FinnO - Fr 13.03.09 19:14
soo ich hab das mal wie UB gesagt hat (bzw. wie ich es verstanden habe) gemacht...
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| type TZeichnen = Class
procedure SetCanvas(Canvas : TCanvas); function GetCanvas : TCanvas; property FCanvas read GetCanvas write SetCanvas; end;
implementation
{$R *.dfm}
procedure TZeichnen.SetCanvas(Canvas : TCanvas); begin FCanvas := Canvas end;
procedure TZeichnen.GetCanvas : TCanvas begin result := FCanvas; end;
procedure TForm1.Form1Create(Sender : TObject); var Z : TZeichnen; begin Z.FCanvas.Ellipse(100,100,200,200); end; |
Wodran liegts?
elundril - Fr 13.03.09 19:23
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| type TZeichnen = Class private FCanvas: TCanvas public procedure SetCanvas(Canvas : TCanvas); function GetCanvas : TCanvas; published property Canvas read GetCanvas write SetCanvas; end;
implementation
{$R *.dfm}
procedure TZeichnen.SetCanvas(Canvas : TCanvas); begin FCanvas := Canvas end;
procedure TZeichnen.GetCanvas : TCanvas begin result := FCanvas; end;
procedure TForm1.Form1Create(Sender : TObject); var Z : TZeichnen; begin Z := TZeichnen.Create; Z.Canvas := TForm1.Canvas; Z.Canvas.Ellipse(100,100,200,200); end; |
so sollte es schon eher funktionieren denke ich.
lg elundril
Marc. - Fr 13.03.09 19:24
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.Form1Create(Sender : TObject); var Z : TZeichnen; begin Z.SetCanvas(...); Z.FCanvas.Ellipse(100,100,200,200); end; |
IMHO solltest du auch die Setter Methode aufrufen, bevor du auf ein nicht referenziertes Canvas zugreifst. ;)
FinnO - Fr 13.03.09 19:25
@ elundril: negativ :(
@Marc. + Elundril: Kombiniert klappts, beim Beenden kriege ich noch folgende Exception:
"Externe Exception"
ub60 - Fr 13.03.09 20:22
Was ich meinte, geht etwa so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| type TZeichnen = Class protected FCanvas : TCanvas; public procedure SetCanvas(Canvas : TCanvas); procedure ZeichneKreis(x,y,r:Integer); function GetCanvas : TCanvas; end;
var Form1: TForm1;
implementation
{$R *.dfm}
function TZeichnen.GetCanvas: TCanvas; begin Result:=FCanvas; end;
procedure TZeichnen.SetCanvas(Canvas : TCanvas); begin FCanvas := Canvas; end;
procedure TZeichnen.ZeichneKreis(x,y,r:Integer); begin FCanvas.Ellipse(x-r, y-r, x+r, y+r); end;
procedure TForm1.FormCreate(Sender : TObject); var Z : TZeichnen; begin Z:=TZeichnen.Create; Z.SetCanvas(Image1.Canvas); Z.ZeichneKreis(100, 150, 50); Z.Free; end; |
ub60
Xentar - Fr 13.03.09 21:03
ub60 hat folgendes geschrieben : |
Was ich meinte, geht etwa so:
Delphi-Quelltext 1: 2: 3:
| public procedure SetCanvas(Canvas : TCanvas); function GetCanvas : TCanvas; | |
Genau das macht doch ein Property - nur eben als eine Eigenschaft.
Yogu - Fr 13.03.09 22:02
Äh, jetzt nochmal im Klartext: Die Zugirffsverletzung kam, weil das Objekt
Z (übrigens ein sehr gut gewählter Bezeichner für eine
Zeichenklasse ;)) nicht initialisiert wurde.
ub60 hat die fehlende Zeile in seinem Code eingeführt.
Aber so, wie die Klasse bis jetzt definiert ist, könnte man noch einiges rausschmeißen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| type TZeichnen = class private fCanvas: TCanvas; public procedure ZeichneKreis(x, y, r: Integer);
property Canvas: TCanvas read fCanvas write fCanvas; end;
implementation
procedure TZeichnen.ZeichneKreis(x, y, r: Integer); begin fCanvas.Ellipse(x-r, y-r, x+r, y+r); end;
procedure TForm1.FormCreate(Sender : TObject); var Zeichner : TZeichnen; begin Zeichner := TZeichnen.Create; try Zeichner.SetCanvas(Image1.Canvas); Zeichner.ZeichneKreis(100, 150, 50); finally Zeichner.Free; end; end; |
FinnO - Sa 14.03.09 00:23
hmm also ersteres war klar ^^
zweiteres Wusste ich gar nicht :oops:
aber jetzt ist alles Klärchen... danke
Ich geb euch doch nicht den Code von meiner Turtle ;) da muss schon mal ne Zeichenklasse Z zur verdeutlichung herhalten :evil:
:closed:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!