Ein eigenes Koordinatensystem
-
Hallo
Wie property verwendet wird, steht ausführlich in dem Tutorial, das ich in meinem ersten Post in diesem Thread verlinkt habe. Unterseite "Methoden, Eigenschaften und Ereignisse", Abschnitt Eigenschaften.
bis bald
akari
-
Da durchforstet man die ganze Hilfe und es steht im zweiten Post. *schäm*
Danke für den Hinweis! Ich habs hinbekommen.
lg, freakC++
-
Wenn ich beispielsweise möchte, dass xMax als default Wert die Breite meiner Zeichenfläche hat, so habe ich xMax einfach im Konstruktor den entsprechenden Wert zugewiesen:
TGraph.h
class PACKAGE TGraph : public TPaintBox { private: int XMAX; protected: public: __fastcall TGraph(TComponent* Owner); __fastcall void ShowXMAX () {ShowMessage(XMAX);}; __published: __property int xMax = {read = XMAX, write = XMAX}; };
TGraph.cpp
__fastcall TGraph::TGraph(TComponent* Owner) : TPaintBox(Owner) { XMAX = Width; }
Das ist zwar von der Syntax korrekt, doch das Ergebnis ist dennoch falsch. Bei mir erscheint im Objektinspektor 105, obwohl das Objet Graph1 viel länger ist.
Es liegt wohl daran, dass diese Anweisung im Konstruktor steht. Doch wie könnte man das Problem denn am besten lösen, da schon Anfgans xMax dieser Wert zugewiesen werden soll
Vielen Dank
lg, freakC++edit: Ich habe das Problem gelöst, indem ich einfach die Zuweisung XMAX=Width in akaris DoPaint Methode geschrieben habe. Doch ist das die einzige Möglichkeit, das Problem zu lösen. Sollte man solche Zuweisungen generell nicht in den Konstruktor schreiben?
-
Wenn du auf Größenänderungen deines Controls reagieren willst bzw. dein XMAX
festlegen willst dann kanst du das OnResize Event reagieren.freakC++ schrieb:
edit: Ich habe das Problem gelöst, indem ich einfach die Zuweisung XMAX=Width in akaris DoPaint Methode geschrieben habe. Doch ist das die einzige Möglichkeit, das Problem zu lösen. Sollte man solche Zuweisungen generell nicht in den Konstruktor schreiben?
Wenn du das Property XMAX in DoPaint immer mit der Breite der Komponente
setzt, wiso hast du Überhaupt das XMAX Property ? dann kannst du auch gleich
das Width verwenden.
Wenn dein Koordinatensystem von außen Steuerbar sein soll, sollte der Benutzer
das XMAX und die anderen min/max Einstellungen selbst Eingeben können und du
nur auf Fehleingaben hinweisen und nicht selbst die Property im Control setzten.
-
Hallo VergissEs,
dein letztes Argument ist natürlich klar. Ich habe XMAX auch nur Width zugewiesen, um zu überprüfen, ob alles funktioniert. Zuerst hat es eben nicht funktioniert und somit habe ich eine mögliche spätere Fehlerquelle schon behoben. Width wird natürlich nur in irgendeinem Verhältnis zu XMAX stehen. Ich möchte halt, dass sich das Koordinatenkreuz automatisch anpasst. WIe ich das mache steht noch nicht fest....da muss ich mir noch ein paar Gedanken machen. Außerdem sollen XMAX etc. im Objektinspektor erscheinen, was sonst nicht der Fall wäre. Das OnResize Event kannte ich noch gar nicht. Das hört sich sehr gut an. ICh werde es mir bald anschauen.Ganz am Anfang dieses Threads hast Du mir gesagt, wie ich den Nullpunkt verschiebe. Dazu habe ich bezüglich noch eine Frage:
HDC hDC = Canvas->Handle; MoveWindowOrg(hDC, 300, 200);
Somit kann ich den Ursprung meines Koordinatensystems nach (300|200) verlegen. Doch was ich der Typ HDC? Das funktioniert auch:
SetViewportOrgEx(Canvas->Handle, Width/2, Height/2, NULL);
SPielt es eine Rlle, wann ich welchen Befehl erteile, denn beide machen ja das gleiche.
Vielen Dank
lg, freakC++
-
HDC ist ein Handle Device Context also das Handle der Zeichenfläche auf der du zeichnest (WinAPI).
MoveWindowOrg und SetViewportOrgEx machen erstmals das selbe aber du kannst noch mehr bei den Koordinaten manipulieren siehe:
http://msdn.microsoft.com/en-us/library/dd183475(VS.85).aspx
-
Ahh...super! Wieder was gelernt. Dann frage ich mich jedoch, warum es nicht möglich, die Nullpunktverschiebung direkt in akaris "DoPaint" Methode zu schreiben:
void __fastcall TGraph::DoPaint(TObject *Sender) { SetViewportOrgEx(Canvas->Handle, Width/2, Height/2, NULL); SetMapMode(Canvas->Handle, MM_LOENGLISH); }
Als Test habe ich mal das geschrieben, doch der Nullpunkt bleibt oben links:
Graph1->Canvas->LineTo(100,100);
Warum kann ich die Anweisung nicht in die DoPaint Methode schreiben. Liegt es daran, dass ich diese dem OnPaint Event zuweise?
Soweit ich das weiß gibt es in der Klasse TPaintBox kein OnResize Event !? Deswegen kann ich VergissEs' Tipp nicht umsetzen.
Wo sollte ich denn am besten die Nullpunktverschiebung reinschreiben?
Vielen Dank
lg, freakC++
-
Ich habe nochmal ein bisschen ausprobiert. Wenn ich folgendes in die DoPaint Methode schreibe:
SetViewportOrgEx(TGraph::Canvas->Handle, Width/2, Height/2, NULL); SetMapMode(TGraph::Canvas->Handle, MM_LOENGLISH); Canvas->LineTo(200,200);
dann wird die Linie nicht vom gewünschten Nullpunkt gezeichnet. Wenn jedoch das schreibe:
SetViewportOrgEx(TGraph::Canvas->Handle, Width/2, Height/2, NULL); SetMapMode(TGraph::Canvas->Handle, MM_LOENGLISH); TGraph::Canvas->LineTo(200,200);
dann wird die Linie "korrekt" gezeichnet. Wenn ich dann jedoch einen Button erstelle mit dem Code
Graph1->Canvas->LineTo(100,100);
dann wird nicht vom gewünschten Nullpunkt gezeichnet. Verliert die Verschiebung des Ursprungs da ihre Wirkung oder was muss ich machen, damit dieser immer verschoben bleibt?
Vielen Dank für eure Hilfe
lg, freakC++PS.: SOll ich eigentlich für solche Fragen einen neuen Thread aufmachen, da das ja mit dem Anfangsthema nichts mehr zu tun hat?
-
Hallo
Ich habe keine Erfahrung mit dem SetViewport..., aber in deinem Code ist das "Graph1->" schonmal falsch. Nocheinmal : Für deine neue Komponente müßen alle Zeichenoperationen in der TGraph::DoPaint-Methode erfolgen. Dazu steht dir die Eigenschaft Canvas zur Verfügung. Du brauchst auch nicht "TGraph::" zu benutzen. "Graph1->" ist aber gar ein Fehler. Denn in der DoPaint-Methode gibt es keine konkrete Graph1-Instanz, du schreibst doch schließlich eine allgemeine, mehrfach verwendbare Komponente.
Noch passt das in diesen Thread...
bis bald
akari
-
Nein, das "Graph1->" steht in einer ButtonClick Methode. Das war ein Text, um zu überprüfen, ob nun der Nullpunkt endlich korrekt verschoben worden ist. Leider hat dieser Test halt ergeben, dass dies nicht der Fall ist. Dennoch wird die Linie, die in der DoPaint Methode gezeichnet wird, korrekt gezeichnet (also ab dem gewünschten NullPunkt in der Mitte meiner KOmponente).
Ich verstehe also nicht, warum ich auf mein Graph Objekt nicht ab dem in der DoPaint-Methode festgelegten Nullpunkt zeichnen kann.
Wer weiß da weiter?
Vielen Dank, akari
lg, freakC++
-
Hallo
Nocheinmal : Für deine neue Komponente müßen alle Zeichenoperationen in der TGraph::DoPaint-Methode erfolgen
Egal wo du diese OnButton-Methode definiert hast, dort ist nunmal der Zugriff auf TGraph::Canvas nicht korrekt. Wenn dann solltest du von dem Button aus eine von deinen für TGraph neu implementierten Eigenschaften setzen. Mit TGraph::Refresh() löst du dann das Paint-Event aus, in dem dann die Eigenschaften ausgewertet werden und die Zeichenoperationen ausgeführt werden.
bis bald
akari
-
Aber ich habe den Button auf meinem Forumar und habe ich eine Instanz von TGraph erstellt, auf die zeichnen möchte. Diese Zeichenanweisung steht in einem Button.
Naja, egal. Auf jeden Fall stimmt dieser Code nicht und ich weiß einfach nicht warum:
void __fastcall TGraph::DoPaint(TObject *Sender) { SetViewportOrgEx(Canvas->Handle, Width/2, Height/2, NULL); SetMapMode(Canvas->Handle, MM_LOENGLISH); Canvas->MoveTo(0,Height/2); Canvas->LineTo(0,-Height/2); }
NUn sollte wenigstens die Y Achse gezeichnet werden, doch diese ist einfach nicht in der Mitte und sie geht noch nichtmal durch die ganze Graph KOmponente.
Könnt ihr mir da bitte weiterhelfen?Vielen DAnk :xmas1:
lg, freakC++
-
Du musst nach dem zeichnen den Urzustand wieder herstellen.
//Hintergrund mit Gradient überzeichnen GradientFillCanvas(Canvas, clWhite, clBlue, ClientRect, gdVertical); SetViewportOrgEx(Canvas->Handle, Width/2, Height/2, NULL); Canvas->Pen->Style = psSolid; Canvas->Pen->Color = clBlack; //Horizontale Linie Canvas->MoveTo(0, Height/2); Canvas->LineTo(0, -Height/2); //Vertikale Line Canvas->MoveTo(Width/2, 0); Canvas->LineTo(-Width/2, 0); //Urzustand wieder herstellen SetViewportOrgEx(Canvas->Handle, 0, 0, NULL);
-
Hey VergissEs,
vielen Dank für deine Hilfe. Zwei Anliegen habe ich:1.) Was ist GradientFillCanvas und der Parameter gdVertica. Die Hilfefunktion und Google kennen beides nicht (google verweist nur auf dich :D). Was muss ich machen, um diese Funktion zu nutzen.
2.) KÖnntest Du mir nochmal genau sagen, warum ich den Urzustand wiederherstellen muss. Was genau ist der Urzustand? Warum kann ich in der Do-Paint Methode nicht einfach den Nullpunkt ändern und dann eine Linie zeichnen. Diese Linie würde nicht vom Zentrum meiner KOmponente gehen.
Bitte helft mir, auch wenn das schon ein riesen Thread ist. Ich gebe zu, dass Th69 Aussage hier stimmt: Ich bin nämlich momentan ein bisschen unbeholfen und weiß einfach nicht, wie das Problem lösen kann (also dass ich dauerhaft den Ursprung verschieben kann).
Ich danke euch sehr!
lg, freakC++
-
freakC++ schrieb:
1.) Was ist GradientFillCanvas und der Parameter gdVertica. Die Hilfefunktion und Google kennen beides nicht
-
Ok, danke. Das werde ich mir mal anschauen. Doch wozu ist diese "Gradientfüllung" hier nützlich. Außerdem:
Muss ich immer den Nullpunkt vor jeder Zeichnung neu verschieben. Ist eine Verschiebung nur temporär? Warum kann ich diesen nicht dauerhaft verschieben?
Vielen Dank für eure tolle Hilfe
lg, freakC++PS.: Ich mach morgen mal einen neuen Thread auf, weil sich dieser sehr aufbläht, keine richtige Überschrift hat und gar nichts mehr mit dem Anfangsthema zu tun hat. Dann haben es andere leichter ihn über die Suchfunktion zu finden. Ich hoffe das ist ok, akari?
-
freakC++ schrieb:
Muss ich immer den Nullpunkt vor jeder Zeichnung neu verschieben. Ist eine Verschiebung nur temporär? Warum kann ich diesen nicht dauerhaft verschieben?
Hallo,
wenn du die gepostete Funktion von Th69 genau betrachtest, hast du schon die Lösung.
Bei gleichen Werten für (zB) xmin = -5 und xmax = 5, ebenso für die Y-Achse ist dein System zentriert.Naja, wird schon
.
mfg
kpeter
-
Hallo,
Naja, wird schon .
Das hoffe ich auch, doch langsam glaube ich nicht mehr an mich. Auch wenn ihr es schon gesagt habt, dann schaut euch doch bitte dieses Beispiel mal an. Vielleicht verstehe ich euch falsch, vielleicht verstehe ich die Funktion SetViewportOrgEx nicht, vielleicht bin ich einfach zu doof.
Ich habe wie schon gesagt, akaris Do-Point Methode und eine Methode "Nullpunkt", die nichts anderes macht, außer den Nullpunkt zu verschieben:void __fastcall TGraph::Nullpunkt() { HDC hDC = Canvas->Handle; SetMapMode(hDC, MM_TEXT); SetViewportOrgEx(Canvas->Handle,ClientWidth/2, ClientHeight/2, NULL); Canvas->MoveTo(0,0); } //--------------------------------------------------------------------------- void __fastcall TGraph::DoPaint(TObject *Sender) { xmin = -Width/2; xmax = Width/2; ymin = -Height/2; ymax = Height/2; Nullpunkt(); Canvas->Pen->Style = psSolid; Canvas->Pen->Color = clBlack; Canvas->MoveTo(0, Height/2); //das kommt auch von euch ;) Canvas->LineTo(0, -Height/2); Canvas->MoveTo(Width/2, 0); Canvas->LineTo(-Width/2, 0); SetViewportOrgEx(Canvas->Handle, 0, 0, NULL); //Wiederherstellung der urprünglichen Nullpunktes }
Wenn ich nun eine Instanz von TGraph auf mein Formular ziehe, dann wird das Koordinatenkreuz schön gemalt und alles läuft super. Jetzt kommt das für mich völlig "Unlogische" und ich bitte wirklich um eure Geduld, denn ich will was lernen:
Ich habe mir eine eigene LineTo Methode geschrieben, die vor einer Zeichnung den Nullpunkt verschiebt.
void __fastcall TGraph::Linie(int a, int b) { Nullpunkt(); //Verschiebung des Nullpunkts und zum Nullpunkt gehen Canvas->LineTo(a,b); //ab dem Nullpunkt zeichnen SetViewportOrgEx(Canvas->Handle, 0, 0, NULL); //wieder den ursprünglichen Nullpunkt herstellen }
Nun habe ich das mal ausprobiert. Ich habe einen Button und eine Instanz von TGraph auf meinem Formular und die Anweisung in meinem Button lautet:
Graph1->Linie(200,200);
Wenn ich nun auf meinem Buttton klicke, wird zwar eine Linie gezeichnet, aber nicht vom gewünschten Ursprung (also dort wo sich x und y Achse schneiden). Hier liegt mein Problem, das ich trotz eines riesen Thread uns massig Antworten nicht zu lösen vermag. Wenn ich meine TGraph Instanz auf dem Formular verschiebe, dann erscheint bei Knopfdruck an anderer Stelle die Linie.
Entweder habe ich irgendwas grundsätzlich nicht verstanden oder ich übersehe die ganze Zeit etwas. Bitte helft mir nochmals und erklärt mir, wie ich richtig zeichnen Kann.
Danke!
lg, freakC++, der langsam verzweifelt und sich schon sehr doof fühlt
-
Wiso willst du von außerhalb in den Graphen zeichnen?
Wiso nicht einfach die Zeichenkoordinaten übergeben und die Komponente kümmert sich um das zeichnen im OnPaint.
Wenn du wiso von ausserhalb auf die neu erstellte Komponete zeichnen willst, wiso erstellst du überhaupt eine Komponente? ... kannst ja auch gleich die PaintBox selbst verwenden und alles im OnPaint Zeichnen lassen und evtl. später
wenn dein Graph alles macht was du willst in eine Komponente stecken und diese nur noch über die Eigenschaften steueren (auch die Zeichendaten).
-
Hallo,
nein das möchte ich auch nicht. DAs Problem ist einfach nur, dass auch falsch gezeichnet wird, wenn ich die Komponente selber zeichnen lassen möchte. Sieh dir mal das an:void __fastcall TGraph::Zeichne() { Nullpunkt(); //Nullpunktsetzung Canvas->LineTo(200,200); //Zeichne VOM Nullpunkt SetViewportOrgEx(Canvas->Handle, 0, 0, NULL); //Zurücksetzen }
Wen ich jetzt in meiner Button Anweisung das schreib:
Graph1->Zeichne();
dann wird auch nicht von meinem gewünschten Nullpunkt gezeichnet. Das verstehe ich nicht.
Warum wird in der OnPaint Methode, das Koordinatenkreuz korrekt gezeichnet, aber sobald ich eine andere Zeichnung mache, wird für mich an einem wahllosen Punkt angefangen, obwohl ich "Nullpunkt" aufgerufen habe. Ein anderes Problem liegt ja eigentlich gar nicht vor. Ich habe nur halt schon so viel ausprobiert, weshalb Methoden wie "Zeichne" oder "Linie" zustande kommen. Später wird das natürlich anders aussehen, doch erstmal will ich halt, dass korekt gezeichnet wird, da sonst nie ein Graph zustande kommt.
Vielen Dank, VergissEs! Kannst Du oder jemand anderes sagen, warum das Ergebnis von anderen Zeichnungen nicht meinen ERwartungen entsprechen und warum nur in OnPaint richtig gezeichnet wird. Vielleicht habe ich ja uch grundsätzlich etwas nicht verstanden!
Bis bald
lg, freakC++edit: Ich habe nochmal ein bisschen rumgespielt. ALle ZEichnungen aus DoPaint werden korrekt gezeichnet, doch alle anderen, wie solche in MEthoden wie "Zeichne" werdden "falsch" gezeichnet.