AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Canvas als Property übergeben...

Ein Thema von heiopei · begonnen am 26. Sep 2007 · letzter Beitrag vom 26. Sep 2007
Antwort Antwort
heiopei
(Gast)

n/a Beiträge
 
#1

Canvas als Property übergeben...

  Alt 26. Sep 2007, 15:33
Hallo,
ich bin dabei, eine Komponente zu entwickeln, der ein Canvas als Property zugewiesen werden soll.
Die Komponente soll dann auf das Canvas zeichnen können...

Außerdem möchte ich eine Komponente entwerfen (Komponente 1), die sowohl oben beschriebene Komponente (Komponente 2) als auch ein Bitmap enthält. Dem Canvas von Komponente 2 soll nun das Canvas des Bitmaps von Komponente 1 zugewiesen werden.

Also etwa so

- Komponente 2
|_Canv: TCanvas;
|... Zeichnen-Funktionen, die auf das Canvas Zeichnen

- Komponente 1
|_ Bild: TBitmap; .Canvas-----------
|_ Komp2: TKomponente2; |
|_Canv := <---------------------

Hoffe man versteht die Grafik
Die Zuweisung des Canvas erfolgt natürlich erst z.B. bei der Erzeugung von Komponente 1.


Meine Fragen:
a) wie muss ich das property "Canv" genau definieren, damit ich keine AV bekomme
(ich würde sagen property Canv: TCanvas read FCanv write SetCanv; wobei SetCanv dem Feld FCanv
mittels FCanv.Assign den Übergabewert zuweist)
b) wie muss ich dem property Canv einen Canvas übergeben
(einfach Komp1.Canv := Bild.Canvas ?!?)

Ich bekomme immer eine AV, oder es passiert nichts.

Danke im vorraus,
heiopei

PS: sorry, dass ich das so theoretisch und ohne code-beispiel mache, aber es fällt mir so irgendwie leichter, das Problem zu beschreiben.



Edit: Ich habe gerade nochmal folgendes getestet:
a) eine Komponente 2 namens Comp2
b) ein TImage namens Image1
c) eine Zuweisung auf Buttonclick: Comp2.Canv := Image1.Canvas;
=> Es kommt die Fehlermeldung: 'Cannot assign a TBitmapCanvas to a TCanvas.'

(Canv wurde als property wie oben von mir vorgeschlagen definiert, also mit Setter-Funktion)

Wo hängt's?
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

Re: Canvas als Property übergeben...

  Alt 26. Sep 2007, 15:53
Zitat von heiopei:
PS: sorry, dass ich das so theoretisch und ohne code-beispiel mache, aber es fällt mir so irgendwie leichter, das Problem zu beschreiben.
Wäre aber sinnvoll, wenn du dein ursprüngliches Problem schildern würdest.
Normalerweise hat jedes Control seinen eigenen Canvas.
Komponenten, die einen externen Canvas benötigen gibt es in der ganzen VCL nicht.
(und das nicht ohne Grund)
Wenn du jetzt also eine Komponente bauen möchtest, die einen externen Canvas benötigt,
dann liegt hier eigentlich schon ein Designfehler vor.
Denn mit dem Canvas allein ist es ja nicht getan. Die Komponente müsste zusätzlich wissen, wie gross die Zeichenfläche ist.
Bei Controls kann dieses Problem gar nicht auftreten; ein Control weiss immer wie gross sein eigener Canvas ist.
Andreas
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#3

Re: Canvas als Property übergeben...

  Alt 26. Sep 2007, 15:57
Und wenn würde ich einen internen Canvas mit dem externen koppeln
Markus Kinzler
  Mit Zitat antworten Zitat
heiopei
(Gast)

n/a Beiträge
 
#4

Re: Canvas als Property übergeben...

  Alt 26. Sep 2007, 16:12
Hi,

Zitat von mkinzler:
Und wenn würde ich einen internen Canvas mit dem externen koppeln
und was dat des jetz konkret bedeuten?


Zitat von shmia:
Wenn du jetzt also eine Komponente bauen möchtest, die einen externen Canvas benötigt,
dann liegt hier eigentlich schon ein Designfehler vor.
Also ich könnte das ganze natürlich auch in Komponente 1 packen, hab mir aber gedacht es wäre schöner, die Zeichen-Funktionen in eine extra Komponente zu packen, um das Ganze übersichtlicher und flexibler zu gestalten. Dann bräuchte Komponente 2 nur ein Canvas als Property auf das es zeichnen soll...

Zitat von shmia:
Denn mit dem Canvas allein ist es ja nicht getan. Die Komponente müsste zusätzlich wissen, wie gross die Zeichenfläche ist.
Bei Controls kann dieses Problem gar nicht auftreten; ein Control weiss immer wie gross sein eigener Canvas ist.
Sorry, hab vergessen, das noch dazu zu sagen - die Maße vom Bitmap sind auch als Propertys in Komponente 2 vorhanden.

Um das ganze vielleicht durchschaubarer zu machen, muss ich glaub ich dich noch erwähnen, was ich eigentlich machen will :

ich möchte eine Komponente entwickeln, auf der Funktionen ausgegeben werden sollen, also ein Graph.
Dazu möchte ich dieser Komponente, nennen wir sie TGraph (-> Komponente 1), eine Komponente TKoordinatenSystem (Komponente 2), sowie eine PaintBox zuweisen.
Da PaintBox ja seine Grafik nicht speichert, muss ich noch eine Variable Bild vom Typ TBitmap einführen. So.
TKoordinatenSystem soll jetzt ein KoordinatenSystem mit bestimmten Parametern auf das Bitmap zeichnen.
Außerdem zeichnet dann noch eine weitere Komponente die Funktionen auf das Bitmap, diese ist jetzt aber uninteressant. Jetzt muss nur noch das Bitmap auf TPaintBox gezeichnet werden (und bei jedem Paint-Ereignis) - und fertig! (oder nicht?)

bis dann,
heiopei
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#5

Re: Canvas als Property übergeben...

  Alt 26. Sep 2007, 16:26
Zitat von heiopei:
ich möchte eine Komponente entwickeln, auf der Funktionen ausgegeben werden sollen, also ein Graph.
..
Jetzt muss nur noch das Bitmap auf TPaintBox gezeichnet werden (und bei jedem Paint-Ereignis) - und fertig! (oder nicht?)
Muss dann die Komponente wirklich ein Canvas-Property haben ?
So geht's doch auch (und ist sehr flexibel):
Delphi-Quellcode:
procedure TForm1.Paintbox1Paint(Sender:TObject);
const
  xoffset = 0;
  yoffset = 0;
begin
  FMyGraph.Width := Paintbox1.Width;
  FMyGraph.Height := Paintbox1.Height;
  // die Graph-Komponente hat eine Methode PaintTo
  FMyGraph.PaintTo(Paintbox1.Canvas, xoffset, yoffset);
end;
Und wenn du dann Drucken möchtest:
Delphi-Quellcode:
  Printer.BeginDoc;
  FMyGraph.Width := .. ; // ermitteln, wie viel Platz auf dem Printer Canvas ist und beide Ränder anziehen
  FMyGraph.Height := ..; // dito
  Printer.Canvas.TextOut(150, 160, 'Funktionsplot...');
  FMyGraph.PaintTo(Printer.Canvas, 150, 180);
Andreas
  Mit Zitat antworten Zitat
heiopei
(Gast)

n/a Beiträge
 
#6

Re: Canvas als Property übergeben...

  Alt 26. Sep 2007, 16:55
[quote shima]
FMyGraph.PaintTo(Paintbox1.Canvas, xoffset, yoffset);
[/quote]

Wenn sich ein Property ändert, so muss das ganze Koordinatensystem neu gezeichnet werden.
Das mache ich, indem ich eine Prozedur "PropertyChanged" aufrufe, so bald ein Property geändert wird.
Diese wiederum leert die Canvasoverfläche, Zeichnet das Koordinatensystem neu und löst ein Ereignis "OnPropertyChanged" auf, um es der verwendenden Komponente zu erlauben, darauf durch z.B. neu zeichnen der Funktionen und Ausgabe auf der Paintbox zu reagieren.

Wenn ich es so machen würde, wie du beschreibst (also Übergabe des Canvas als Funktionsparameter), dann müsste ich die verwendende Komponente jedes mal benachrichtigen, dass neu gezeichnet werden soll und alle zeichenaktionen von dieser ausführen lassen; d.h. die verwendende Komponente müsste auf das OnPropertyChanged-Event reagieren, indem es selbst die Zeichnfläche leert, die Koordinaten-System-Zeichenfunktion von TKoordinatenSystem aufruft, die Funktionen neu auf das Bitmap zeichnet und dann das Bitmap auf die PaintBox ausgibt!

Was ist jetzt besser - bin mir nicht sicher!
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#7

Re: Canvas als Property übergeben...

  Alt 26. Sep 2007, 17:13
Ich würde es so machen, wie ich es beschrieben habe.
Deine Graph-Komponente feuert das Event OnPropertyChange ab, wenn sich etwas geändert hat (Wertebereich, Funktion, Stiftfarbe,...)
Das Formular sollte dann folgenden Eventhandler einsetzen:
Delphi-Quellcode:
proecedure TForm1.Graph1PropertyChange(Sender:tObject);
begin
   Paintbox1.Invalidate;
end;
Sollte auf dem Formular statt einer PaintBox ein TImage liegen, dann sähe der Eventhandler so aus:
Delphi-Quellcode:
proecedure TForm1.Graph1PropertyChange(Sender:tObject);
begin
  FGraph1.Width := Image1.Width;
  FGraph1.Height := Image1.Height;
  FGraph1.PaintTo(Image1.Canvas, 0, 0);
end;
Wichtig ist, dass die Methode PaintTo ALLES zeichnet, also Hintergrund löschen,
Koordinatensystem zeichnen, Funktion zeichnen, Legende zeichnen.
Die Methode PropertyChange löscht keinen Hintergrund oder zeichnet ein Koordinatensystem (wie von dir beschrieben), sondern feuert nur das Event ab.
Die Anwendung liefert den "Klebstoff" zwischen deiner Graph-Komponente und jeglichem Ausgabe-Canvas.
Andreas
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:20 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