Ein eigenes Koordinatensystem



  • freakC++ schrieb:

    1.) Was ist GradientFillCanvas und der Parameter gdVertica. Die Hilfefunktion und Google kennen beides nicht

    ➡ hier



  • 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.



  • Bei der VCL ist der 0-Punkt immer oben links wenn du nun in OnPaint den 0-Punkt
    verschiebst dann hat natürlich die VCL Probleme damit, deshalb wieder
    zurückstellen. Dich zwingt auch keiner den 0-Punkt zu verschieben das ganze
    kann auch wie TH69 in seiner Funktion geschrieben hat erfolgen, also die ganzen Koorinaten selbst berechnen.

    Du weisst schon das OnPaint automatisch immer aufgerufen wird zum Beispiel ein anderes Fenster über deinen Graphen gezogen und dann wieder sichtbar wird.
    Wenn du nun eine Zeichenfunktion Graph1->Zeichne(); manuell ausführst wird diese natürlich nicht im OnPaint berücksichtigt.
    Wenn du schon ein neuzeichnen des Graphen erzwingen willst,dann Bitte mit der schon existierenden Graph1->Repaint();
    UND ALLES IN OnPaint zeichnen lassen!



  • Du darfst einfach NICHT außerhalb des OnPaint-Ereignisses zeichnen - PUNKT!

    So langsam zweifel ich auch daran, ob du wirklich den Sinn einer Komponente verstanden hast.
    Ein Button-Click darf allerhöchstens Invalidate() für die PaintBox aufrufen, und dann muß sich die PaintBox selbständig zeichnen (im OnPaint-Ereignis) - so wie akari, VergissEx und kpeter auch schon vorher geschrieben haben!!!

    Du mußt nur dafür sorgen, daß die entsprechenden Parameter für deine PaintBox-Komponente vorher gesetzt sind (per Eigenschaften oder Methoden, welche intern eine Liste von Koordinaten als private Member verwalten o.ä.).

    Sorry, aber ich verabschiede mich jetzt (für diese Jahr) aus diesem Thread - Guten Rutsch...



  • Hallo Th69,
    vielen Dank für deinen Hinweis. Deine Zweifel sind duchaus angebracht, doch kenne ich den Sinn einer Komponente und wusste nicht, dass ich nicht außerhalb des OnPaint Ereignisses zeichnen darf. Ich meinem Buch stand immer soetwas (es hat sich dann auf das Formular bezogen).

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     Canvas->LineTo(200,200),
    }
    

    Hier wird auch ohne OnPaint gezeichnet und es hat funktioniert. So habe ich Canvas kennen gelernt. Naja, ich versuche deinen Tipp anzuwenden. Das bedeutet also, dass ich immer das OnPaint Event aufrufen muss, um zu zeichnen?

    Ich wünsche dir auch einen guten Rutsch und bis nächstes Jahr!
    Vielen Dank für deine Hilfe für einen Anfänger

    lg, freakC++



  • freakC++ schrieb:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     Canvas->LineTo(200,200);
    }
    

    Nach dem Butten Click, schieb mal das Fenster soweit aus dem Bildschirm bis die Linie nicht mehr sichtbar ist und schieb das Fenster wieder auf den Bildschirm dann wirst du festellen das deine gezeichnete Linie nicht mehr da ist.
    Und wiso das so ist.... darft du nun mal dir überlegen 🙂



  • Hallo VergissEs,
    danke auch für deine Antwort. Wie ihr sichlich nun schon mitbekommen habt, bin ich nicht allzu vertaut mit der VCL. Dennoch WILL ich das lernen und bitte darum mir zu heflen, dass hier endlich abzuschließen,.

    Das ich immer innerhalb OnPaint zeichen muss, war mir nicht klar. Daran wird es sicherlich liegen. Natürlich könnte ich alles umrechnen, so wie es TH69 getan hat, doch ich möchte es jetzt so machen, um somit hoffentlich auch einiges zu lernen, damit solche Fragen nicht mehr auftreten. Kannst Du mir mal an einer Methode, die eine Linie nach (200|200) zeichnet, zeigen, wie "ich innerhalb des OnPaint Ereignisses" zeichne. Das gleiche müsste ich dann doch auch mit der Methode "Linie" meiner Komponente TGraph machen? Muss ich da meine Methode "Linie" oder "Zeichne" wie DoPaint OnPaint zuweisen? Könntest DU mir zeigen wie das geht, denn das habe ich nie gelernt und somit würde ich wieder meine Grundlagen erweitern :D.

    Ich möchte halt später Methoden wie DrawGraph oder Ähnliche haben, die wirklich meinen Graphen zeichnen. Wie bringe ich die mit OnPaint in Verbindung, damit richtig gezeichnet wird?

    Bei deinem Beispiel liegt es wohl daran, dass das Fenster nicht neugezeichnet wird. Ja, das ist mir klar, doch wie bringe ich dann das in Verbindung mit OnPaint. Wenn ich das weiß, müsste ja eigentlich alles funktionieren.

    Ich danke dir sehr!
    lg, freakC++



  • Versteh jetzt nicht wo dein Problem ist DrawGraph von DoPaint aus aufzurufen?

    im Header

    private:
    	TColor BackgroundColor;
    	TColor FrameColor;
    	void __fastcall TMyPaintBox::DoPaint(TObject *Sender);
    	void __fastcall DrawBackground();
    	void __fastcall DrawGraph();
    
    __fastcall TMyPaintBox::TMyPaintBox(TComponent* Owner)
    	: TPaintBox(Owner)
    {
    	OnPaint = DoPaint;
    	BackgroundColor = clWhite;
    	FrameColor = clBlack;
    }
    //---------------------------------------------------------------------------
    void __fastcall TMyPaintBox::DrawBackground() {
    
    	Canvas->Brush->Color = BackgroundColor;
    	Canvas->Pen->Color = FrameColor;
    	Canvas->Pen->Style = psSolid;
    
    	Canvas->Rectangle(ClientRect);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMyPaintBox::DrawGraph() {
    
    	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);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMyPaintBox::DoPaint(TObject *Sender)
    {
    
    	//Hintergrund zeichnen
    	DrawBackground();
    
    	//Festlegen das 0/0 Punkt im zentrum liegt
    	SetViewportOrgEx(Canvas->Handle, Width/2, Height/2, NULL);
    
    	//Graphen zeichnen
    	DrawGraph();
    
    	//0/0 Punkt wieder oben links setzen
    	SetViewportOrgEx(Canvas->Handle, 0, 0, NULL);
    }
    //---------------------------------------------------------------------------
    


  • Hallo,
    vielen Dank für den Code, doch leider haben wir uns missverstanden. Nehmen wir an, dass DrawGraph erstmal nichts anderes macht, als eine Linie zu zeichnen:

    void __fastcall TGraph::DrawGraph()
    {
     Canvas->LineTo(200,200);
    }
    

    Nun soll aber DrawGraph nicht von "DoPaint" aufgerufen werden, da der Strich ja schon zu Beginn gezeichnet werden würde. Der Benutzer soll aber selbst bestimmen, wann diese Methode aufgerufen wird und erst z.B. bei Knopfklick den Graphen zeichnen lassen.

    Ich kann, wie ihr mir gesagt habt, nicht einfach DrawGraph() aufrufen, da sie nicht innerhalb von OnPaint zeichnet. Wenn ich das täte, dann würde mein Problem wieder, nämlich, dass nicht vom Ursprung aus gezeichnet wird (auch wenn ich diesen verschoben habe und dahin "gemoved" bin) erscheinen.

    Wie muss ich nun "DrawGraph" modifizieren, damit sie mit OnPaint in Verbindung steht, beziehungsweise, dass die Linie vom Ursprung aus gezeichnet wird?

    Ich hoffe, dass Du mich verstanden hast. Falls Du nicht mehr zum Antworten kommst, wünsche ich dir und auch allen anderen einen guten Rutsch mit vielen Böllern und Raketen :D.
    Vielen Dank für die Hilfe, die hoffentlich bald nicht mehr notwendig ist.
    lg, freakC++



  • Ersteinmal: Frohes Neues!

    Also, wenn es einen Titel hier zu verleihen gäbe, du würdest ihn von mir bekommen: der DAU des Jahres -)

    Du bist anscheinend nicht nur mit der VCL überfordert, sondern auch mit den Grundlagen der Programmierung.

    Für dein Anliegen gibt es zwei einfache Möglichkeiten:
    1. eine Funktion, welche das Ereignis 'OnPaint' aktiviert bzw. deaktiviert (falls du es auch nachträglich wieder nicht-angezeigt haben willst):

    void TMyPaintBox::ActivateGraph(bool bActivate)
    {
      if(bActivate)
         OnPaint = DoPaint;
      else
         OnPaint = 0;
    
      Invalidate(); // zeichnet sich bei Bedarf neu
    }
    

    2. eine boolsche Variable:

    bool bActivateGraph = false; // als Member der Klasse!!!
    
    void TMyPaintBox::ActivateGraph(bool bActivate)
    {
      bActivateGraph = bActivate;
    
      Invalidate();
    }
    
    void TMyPaintBox::OnPaint(...)
    {
      if(!bActivateGraph) return; // zeichne NICHTS!
    
      ...
    }
    

    Und jetzt schreib mir, daß das eine schwere Lösung ist -)

    Lies dir bitte auch nochmal die Hilfe zu Ereignissen (in der VCL) durch...



  • Die Lösung ist nicht zu schwer, doch ich raff' einfach nicht, was das mit meiner zu zeichnenden Linie zu tun hat, die einfach nur vom Nullpunkt ausgehen soll. Jede Linie wird gezeichnet, doch keine vom Ursprung. 😡

    Ich versuche euren ganzen Code anzuwenden, doch es klappt nicht. Egal, ob ich hier oder dort OnPaint schreibe oder den Nullpunkt verschiebe, nur das Koordinatenkreuz wird gezeichnet und jede Linie wird falsch gemalt. Die Methode "DrawLine" zeichnet trotz euer Hilfe immer an der falschen Stelle

    //---------------------------------------------------------------------------
    __fastcall TGraph::TGraph(TComponent* Owner)
            : TPaintBox(Owner)
    {
            OnPaint = DoPaint;
    }
    //---------------------------------------------------------------------------
    namespace Graph
    {
            void __fastcall PACKAGE Register()
            {
                     TComponentClass classes[1] = {__classid(TGraph)};
                     RegisterComponents("Beispiele", classes, 0);
            }
    }
    //---------------------------------------------------------------------------
    void __fastcall TGraph::DrawLine() //was bringt mir hier die boolschen Variable? Ich will doch nur, dass vom Ursprung aus gezeichnet wird? Ich verstehe deinen Code, doch verstehe den Sinn in diesem Problem nicht. Sorry!
    {
     SetViewportOrgEx(Canvas->Handle, Width/2, Height/2, NULL);
     Canvas->MoveTo(0,0);
     Canvas->LineTo(100,100);
    }
    //---------------------------------------------------------------------------
    void __fastcall TGraph::DoPaint(TObject *Sender)
    {
    
     SetViewportOrgEx(Canvas->Handle, Width/2, Height/2, NULL);
     Canvas->MoveTo(0, Height/2);
     Canvas->LineTo(0, -Height/2);
    
     Canvas->MoveTo(Width/2, 0);
     Canvas->LineTo(-Width/2, 0);
     //in diesem Versuch bin ich nicht auf den ursprünglichen Nullpunkt zurückgeganen (siehe VergissEs)
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     Graph1->DrawLine(); //Linie an falscher Stelle
    }
    

    der DAU des Jahres

    Vielleicht hast Du recht, auch wenn das Jahr erst gerade angefangen hat. Trotzdem nicht sehr nett...

    Danke trotzdem
    lg, freakC++

    PS.: Wenn ich das heute nicht hinbekomme, dann gebe ich auf....



  • Hallo,
    so ich habe mich entschieden, dass ich mein Koordinatensystem nun einfach so wie Th69 mache, nämlich ich rechne alles um.

    Zwar finde ich es schade, dass ich es nicht gescahfft habe, den Nullpunkt zu verschieben, doch wie bereits gesagt, kriege ich es einfach nicht hin, eine Linie korrekt vom Nullpunkt aus zu zeichnen.

    Naja, wenn ihr wollt, könnt ihr diesen Thread einfach löschen und wir tun so, also ob nichts gewesen wäre.

    Ich danke euch allen.
    lg, freakC++



  • Hallo

    und ein Gesundes, erfolgreiches und friedliches 2010 allerseits.

    Hab hier noch etwas gefunden, das du lesen solltest,

    bevor du dir die Kugel gibst 😃 .

    bis dann
    kpeter



  • Hallo,
    schau dir mal den Link auf Seite 1 an 😃 ? Aber ich danke dir trotzdem. Bis jetzt gehts aber ganz gut, wenn ich einfach eine Transformation mache. Das Problem liegt einfach daran, dass ich mangelnde Kenntnisse vom Builder habe. Daher würde ich mich freuen, wenn ihr mir sagen könnt, woher ihr das wisst. Irgendwie gibt es keine ausführlichen Bücher darüber.

    Lernt man das an der Uni oder ist das Learning bei Doing? Wie habt ihr das gelenrnt?

    Vielen Dank
    lg, freakC++



  • NOCHMAL die Frage, wiso willst du von ausserhalb auf den Graph zeichnen?

    Wiso willst du überhaupt eine Komponente erstellen die nichts anderes macht als den 0-Punkt zu setzen? dann kann man diese eine Zeile auch direkt in einer PaintBox rein schreiben!

    Wiso erstellst du nicht in deiner Komponente Funktionen wie es normal üblich ist ala Graph1->Items->AddLine(.....) und verwaltest alle Zeichnungsdaten in der Komponente und lässt dann alles im OnPaint zeichnen der Komponente?

    Wir schreiben dir jetzt schon zum zig mal alles in OnPaint zeichnen lassen und dann kommt wieder ein

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     Graph1->DrawLine(); //Linie an falscher Stelle
    }
    

    von dir ... willst du uns was vortrollen? 😡



  • Halt, das ist ein Missverständnis. Ich weiß, dass das nicht stimmt, doch ich wollte auf die DrawLine Methode verweisen, die ich von einem Button aufrufen möchte. Ich wollte halt dass ich von einem Button diese Methode aufrufe und dass dann vom gewünschten Nullpunkt gezeichnet wird. Ich habe es nicht geschafft, euren Code zu anzuwenden, dass dies möglich ist.

    Natürlich soll mein Koordinatensystem noch viel mehr können, doch warum soll ich mir schon Gedanken über weitere Schritte machen, wenn ich es noch nicht mal schaffe, eine Linie zu zeichnen 🙄

    Bitte nicht böse sein! Das diente nur zur Verdeutlichung, dass ich halt diese Methode aufrufen möchte und dass dann vom Nullpunkt aus gezeichnet wird.

    edit: Ich will von außerhalb auf den Graphen zeichnen, weil ich wissen will, wie es geht. Ich bin jemand, der bei einem Problem eigentlich wissen will, warum so etwas ist. Genauso ist es hiert. Ich WILL verstehen, was ich falsch mache und ich WILL wissen, wie ich von außerhalb auf den Graphen zeichne. Auch wenn ich mich wohl doof anstelle!

    lg, freakC++


Anmelden zum Antworten