GDI+ Flankendiagramm zur Laufzeit zeichnen

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von DannyDee.

    GDI+ Flankendiagramm zur Laufzeit zeichnen

    Hallö'chen Leute,
    ich habe hier mal ein neues Thema eröffnet , da es sich ja um andere Grundlagen handelt. Das Projekt ist jedoch das gleiche wie in meinem letzten Thread:


    Kurzerklärung : Mit dem Programm lese ich einen selbstgebauten Inkrementalgeber aus. Ich habe beide Sensoren (A und B) und ihre Stellwerte in Textboxen zwischengelagert. Nun hätte ich gern ein Diagramm welches sich synamisch zur Laufzeit aufbaut, je nachdem wie die Stellposition des jeweiligen Sensors ist.


    Ich hatte mir mal kurz das Tutorial von "FreakJNS" ( ) durchgelesen, doch dort wurde das dynamische erstellen und verschieben von Grafiken nicht näher erläutert.

    Ich hatte mir das über einen Timer gedacht, und zwar habe ich ja einen Timer (timer_lesen) zum auslesen der Stellwerte, in diesen würde ich die Zeichenbefehle mit integrieren. Ich weiß nur nicht genau wie.
    Das ganze soll auf ein Panel gezeichnet werden und ein weiterer Punkt wäre ,dass ich einen "Rahmen" definieren muss ab dem die Zeichnung des Diagramms wieder verschwindet ,da sie ja von rechts nach links verläuft.

    Ich hoffe ich habe euch jetzt nicht damit erschlagen.
    Ein Tutorial dazu wäre ne super Sache. (Und nein ich suche keine C&P-Code , sondern eine schöne gute Anleitung)

    Mit freundlichen Grüßen
    Danny Der Dee
    @DannyDee:: Fang ganz einfach an und Du brauchst kein Tutorial.
    Nehmen wir an, Du willst n disjunkte Sachverhalte darstellen, Form, Panel oder PictureBox ist nicht relevant, gemalt wird im "richtigen" Paint-Event.
    Da brauchst Du in der Klasse n Flags, je eins für jeden Sachverhalt. Initial sind alle Flags auf False - es wird nix dargestellt.
    Dann brauchst Du die Daten, die dargestellt werden sollen. Je nach dem, was es werden soll: Strings, Arrays, Images usw.
    Über einen externen Trigger werden die darzustellenden Daten verändert.
    Sollen Daten dargestellt werden, müssen diese bereitgestellt und das kommunizierende Flag auf True gesetzt werden. Mit xxx.Invalidate() wird der Paint-Befehl aktiviert.
    Im Paint-Ereignis fragst Du nun alle Flags ab und ist eins True, werden die jeweiligen Daten dargestellt.
    Feddich. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ganz am Anfang mal zwei Standardsprüche: "Du musst die GUI von Daten trennen" und "Das Problem in Teilprobleme zerlegen".

    Das heißt du musst dir ein Klassenmodell (oder DataSet) ausdenken, das NUR der Datenhaltung dient. Das könnte z.B. eine Klasse Messpunkt sein, die eben einen einzelnen Messpunkt darstellt. Viele dieser Messpunkte (=> List(of Messpunkt), besser Bindinglist(of Messpunkt) ) könnten nun von einem Control dargestellt werden. Die BindingList feuert Events wenn neue Messpunkte dazukommen - wichtig, denn dann muss das Control sich neuzeichnen. U.U macht es auch Sinn eine Klasse die die Liste verwaltet zu erstellen - also die Klasse 'Messung' beinhaltet viele Messpunkte und bietet vllt Methoden für Durchschnittswerte etc. Die Events der BindingList kannst du über ein eigenes Event (Messung.DataChange?) nach außen leiten. Das Prinzip bleibt aber gleich.
    Wovon du auf jeden Fall wegkommen musst: Daten in Textboxen zu deponieren. Controls zeigen Daten an und bietet Möglichkeiten diese zu manipulieren - speichern/'halten' der Daten ist aber nicht ihre Aufgabe.

    Das Darstellen ist Sache des Controls. Auch die Frage wie dargestellt wird beantwortet das Control (=> Farben, Größe, etc) und bietet dafür Eigenschaften zum einstellen. Hier wäre z.B. auch der von dir genannte "Rahmen" untergebracht - wenn das Control z.B. 500Pixel breit ist werden die letzten 50 Messpunkte dargestellt. Ein Tipp: erstelle eine Klasse MessunktControl und lasse es von Control erben und arbeite in der OnPaint-Methode (ist genau wie das Paint-Event). Das Control findest du dann in der Toolbox und kannst es platzieren wie du möchtest.

    Bis hier hin hast du also nichts weiter als eine Liste von Messpunkten und ein Control, dass diese Liste grafisch und aktuell darstellt. Nun kommt das nächste Teilproblem: das Einlesen der Daten. Egal wie du das machst (ein Timer ist denke ich hier in Ordnung, aber nur EINER! :P ), sobald ein neuer Messpunkt da ist addest du ihn einfach der Liste. Fertig. Die BindingList feuert das entsprechende Event, das Control zeichnet sich neu.



    lg
    @RodFromGermany

    Alles klar , dann schmeiß ich mich mal ran.

    @FreakJNS

    Okey ich verstehe was du meinst.
    Also werde ich erstmal alles zerlegen (in Teilprobleme) und eines nach dem anderen abarbeiten. Ich schätze sein solches "dynamisches" Diagramm ist ein etwas größeres Projekt für einen GDI+-Neuling, also werde ich mich erstmal an deinem Guide festhalten und Schritt für Schritt weiter gehen.
    Das mit dem Klassenmodell ist eine gute Idee ,werde ich auf jeden Fall umsetzen.
    Das Thema "Timer zum auslesen der Daten" ist klar. Ich habe nur einen Timer in der gesamten Form , dieser Timer liest pro Tick das Register der Sensoren aus, und da beide Sensoren im gleichen Register verzeichnet sind, reicht da ein Timer auf jeden Fall , und dieser schmeißt mir den Wert der Stellungen beider Sensoren in einem Integer raus. Dieser sieht (in diesem Falle) wie folgt aus : 1536/1537/1538/1539. Diese stellen die vier möglichen Stellungsvarianten dar. Bisher schmeißt mir der Timer die Werte direkt raus, und ich fange sie mit einem Select-Case ein und wandel sie gleich in Stellung "0" und "1" der einzelnen Sensoren um, welche mir in den Textboxen angezeigt werden.

    Siehe QC:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Timer zum auslesen und Umsetzen des Codes in eine Anzeige der einzelnen Flanken
    2. Private Sub timer_lesen_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timer_lesen.Tick
    3. Select Case readReg(CInt(num_shadr.Value), CInt(num_reg.Value))
    4. Case 1536
    5. tb_flankea.Text = "0"
    6. tb_flankeb.Text = "0"
    7. Case 1537
    8. tb_flankea.Text = "1"
    9. tb_flankeb.Text = "0"
    10. Case 1538
    11. tb_flankea.Text = "0"
    12. tb_flankeb.Text = "1"
    13. Case 1539
    14. tb_flankea.Text = "1"
    15. tb_flankeb.Text = "1"
    16. End Select

    Laut deiner Richtlinie , sollte ich diesen Wert erst in einer Variablen speichern, und dann wiederverarbeiten. Richtig?
    Das wäre ja so an sich kein Problem, nur muss ich für die Drehrichtungsdefinition die Werte der Textboxen auslesen ,da ich den ausgelsenen Wert von z.B.: 1536 nicht aufteilen kann.

    Siehe hier :
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Richtungserkennung Flanke A / Lautstärkenanzeige-Update
    2. Private Sub tb_flankea_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_flankea.TextChanged
    3. If tb_flankea.Text = "1" AndAlso tb_flankeb.Text = "0" AndAlso TextBox1.TextLength < max Then
    4. tb_drehrichtung.Text = "Drehrichtung : Mit dem Uhrzeigersinn!"
    5. TextBox1.Text = TextBox1.Text + "||| "
    6. ElseIf tb_flankea.Text = "1" AndAlso tb_flankeb.Text = "1" AndAlso TextBox1.TextLength > mini Then
    7. tb_drehrichtung.Text = "Drehrichtung : Gegen den Uhrzeigersinn!"
    8. TextBox1.Text = TextBox1.Text.Remove(TextBox1.Text.Length - 4, 4)
    9. End If
    10. End Sub
    11. 'Richtungserkennung Flanke B / Lautstärkenanzeige-Update
    12. Private Sub tb_flankeb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_flankeb.TextChanged
    13. If tb_flankeb.Text = "1" AndAlso tb_flankea.Text = "0" AndAlso TextBox1.TextLength > mini Then
    14. tb_drehrichtung.Text = "Drehrichtung : Gegen den Uhrzeigersinn!"
    15. TextBox1.Text = TextBox1.Text.Remove(TextBox1.Text.Length - 4, 4)
    16. ElseIf tb_flankeb.Text = "1" AndAlso tb_flankea.Text = "1" AndAlso TextBox1.TextLength < max Then
    17. tb_drehrichtung.Text = "Drehrichtung : Mit dem Uhrzeigersinn!"
    18. TextBox1.Text = TextBox1.Text + "||| "
    19. End If
    20. End Sub

    Oder sehe ich den Wald vor lauter Bäumen nicht, und gehe einen Umweg über diese Herangehensweise der Richtungserkennung?


    Nun gut, ich werde mich mal langsam an das Thema GDI+ rantasten. Bei Interesse , würde ich euch auf dem Laufenden halten ,was dieses Projekt angeht.

    MfG
    Danny Der Dee