Ein eigenes Koordinatensystem
-
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ängerlg, 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++
-
Vielleicht solltest du uns nunmal den bisherigen Code der Komponente posten,
ich nehme mal an, die Mods haben nix dagegen und du auch nicht...
-
Hm... jetzt habe ich dir wieder Fragen gestellt und keine davon hast du beantwortet!
-
Hallo,
ich hab' auf deine Fragen geantwortet. Ich will das machen, damit ich es verstehe. Die Komponente soll mehr als den 0 Nullpunkt setzen, aber warum soll ich mir über weitere Schritte Gedanken machen, wenn ich noch nichtmal eine Linie zeichn kann?Ich will dieses ungemütliche Thema jetzt abhaken. Ich glaube, dass wir alle die Nase voll haben und ich mich nicht weiter unbeliebt machen möchte.
Ich probiere das mit der Transformation jetzt aus. Eine Frage habe ich aber noch. Ihr sagtet, dass ich mit "Invalidate()", die PaintBox leeren kann. Das funktioniert leider nicht. Auch Refresh bringt da nichts. Wie kann ich eine PaintBox neu übermalen, sodass das Alte nicht da bleibt. Ich dachte, einfach, das ich sie mit einem Rechteck übermale...also so:
Canvas->Brush->Color=clBtnFace; Canvas->FillRect(Canvas->ClipRect);
Wie muss die Farbe heißen, damit die Komponente wie standargemäß durchsichtig ist? clBtnFace ist da falsch.
Vielen Dank euch
lg, freakC++
-
Invalidate() ruft OnPaint auf und das ist mit deinen DoPaint verknüpft...
-
Möchte wirklich mal wissen, wie er verlangen kann, das wir seine überlangen Postings lesen sollen,
wenn er auf unsere (kurzen) nicht antwortet/reagiert