none
Chart mit Daten füllen RRS feed

  • Frage

  • Hallo,

    ich bastele grade eine Anwendung, die über eine serielle Schnittstelle Daten gesendet bekommt und diese grafisch in einem Chart darstellen soll. Da ich kein Profi bin, probiere ich grad etwas rum. Dabei tritt ein Phänomen auf, das ich nicht verstehe.

    Ich hänge dynamisch Daten an eine DataTable und das klappt bis zum ersten Invalidate des Chart. Danach werden keine Daten mehr angehängt. Um das zu verdeutlichen, habe ich zwei verschachtelte Schleifen eingebaut. 

    Es sollen für meine Spielerei Daten in 200er Häppchen angehängt werden. Schmeiße ich ein Invalidate des Chart nach der inneren Schleife, d.h. nach 200 Daten, kann  ich so viele äußere Schleifen anschmeißen wie ich will, letztendlich werden nur die ersten 200 angezeigt. Direkt nach Ende des letzten äußeren Schleifendurchlaufs gebe ich die Anzahl im Chart enthaltener Daten aus und erhalte da die richtige Anzahl (ja nach Anzahl der äußeren Schleifendurchgänge). Im Chart werden aber nur die ersten 200 angezeigt. Ich fange auch ein Click-Event auf den Chart ab und gebe da die Anzahl der im Chart enthaltenen Daten ebenfalls in eine TextBox aus.

    Ich starte somit meine Testanwendung und rufe die Routine unten auf. Danach zeigt der Graph nur die ersten 200 Datenpunkte, in TextBox steht mit ds.Rows.Count die korrekte Zahl mit 400. Klicke ich danach in den Chart und triggere das Click-Event, wird in TextBox die 400 auf 200 geändert.

    Ich verstehe nicht,

    1) warum nach einem Invalidate des Chart keine weitere danach an die DataTable angehängten Daten angezeigt werden

    2) die Anzahl der Zeilen in der Datentabelle zunächst von der Anzahl angezeigter Daten abweicht

    3) später bei dem Click-Event plötzlich Daten aus der DataTable offensichtlich verschwinden.

    Sachdienliche Hinweise, die mir das Verhalten erklären können werden dankbar entgegengenommen. Ich hoffe, ich konnte mich verständlich machen.

    Gruß

    H. 

    Folgenden Code verwende ich grad:

    Public Sub testChart01()
            Dim ds As New DataTable("tblDaten")
            Dim row As DataRow
            Dim Zufall As New System.Random
            Dim d As New DateTime
            Dim z As Int16 = 0
            'Debug.Print("Debug " & System.Type.GetType("System.DateTime").ToString)
            'ds.Columns.Add(New DataColumn("Zeit", System.Type.GetType("System.DateTime")))
            ds.Columns.Add(New DataColumn("Zeit", System.Type.GetType("System.Int16")))
            ds.Columns.Add(New DataColumn("T", System.Type.GetType("System.Double")))
            ds.Columns.Add(New DataColumn("Ti", System.Type.GetType("System.Double")))
            frmMain.Chart.Series("Series1").XValueMember = "Zeit"
            frmMain.Chart.Series("Series1").YValueMembers = "T"
            frmMain.Chart.Series("Series2").XValueMember = "Zeit"
            frmMain.Chart.Series("Series2").YValueMembers = "Ti"
            frmMain.Chart.DataSource = ds
    
            With frmMain
                .TextBox.Text = "Start"
    
                For j As Integer = 0 To 1
    
                    For i As Integer = 0 To 200
                        .TextBox.Text = "j=" & j.ToString("00") & "    i=" & i.ToString("00") & "  Anzahl Daten=" & ds.Rows.Count
                        row = ds.NewRow()
                        'row("Zeit") = CDate(Now)
                        row("Zeit") = z
                        z = z + 1
                        row("T") = Zufall.NextDouble
                        row("Ti") = Zufall.NextDouble
                        ds.Rows.Add(row)
                        '.Chart.Invalidate()
                        .Refresh()
                        'Application.DoEvents()
                        'Threading.Thread.Sleep(123)
                    Next
                    'Threading.Thread.Sleep(100)
                    .Chart.Invalidate()
                    '.Refresh()
                    'Application.DoEvents()
                Next
                '.TextBox.Text = "fertig"
                .Chart.Invalidate()
                .Refresh()
                'Application.DoEvents()
            End With
    
        End Sub
    

        Private Sub Chart_Click(sender As Object, e As EventArgs) Handles Chart.Click
            TextBox.Text = Now & " Anzahl Datenpunkte: " & Chart.Series("Series1").Points.Count
        End Sub
    


    Mittwoch, 2. Mai 2018 10:00

Antworten

  • Hi,

    in deinem Fall (zumindest im Beispiel) ist "Chart.Invalidate()" nicht ganz das richtige. Nimm "Chart.DataBind()", damit funktioniert (dein Beispiel).

    Ein kleiner Tip am Rande; die Namensgebung deiner Controls ist eher ungünstig. "Chart" und "TextBox" sind Typen, deine Controls sollten so nicht heißen.

    Gruß, Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    • Als Antwort markiert Hannebambel Mittwoch, 2. Mai 2018 11:48
    Mittwoch, 2. Mai 2018 11:11

Alle Antworten

  • Hi,
    ich habe das mal nachgestellt und etwas korrigiert. Außerdem solltest Du mit Option Strict On arbeiten. Hier meine Demo. Einfach mit der Maus auf die TextBox klicken.

    Imports System.Windows.Forms.DataVisualization.Charting
    
    Public Class Form1
    
      Dim Chart As New Chart With {.Dock = DockStyle.Fill}
      Dim WithEvents TextBox As New TextBox With {.Dock = DockStyle.Top}
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Chart.Series.Add(New Series("Series1"))
        Me.Chart.Series.Add(New Series("Series2"))
        Me.Chart.ChartAreas.Add(New ChartArea())
        Me.Controls.AddRange(New Control() {Chart, TextBox})
        ds.Columns.Add(New DataColumn("Zeit", System.Type.GetType("System.Int16")))
        ds.Columns.Add(New DataColumn("T", System.Type.GetType("System.Double")))
        ds.Columns.Add(New DataColumn("Ti", System.Type.GetType("System.Double")))
        Me.Chart.Series("Series1").XValueMember = "Zeit"
        Me.Chart.Series("Series1").YValueMembers = "T"
        Me.Chart.Series("Series2").XValueMember = "Zeit"
        Me.Chart.Series("Series2").YValueMembers = "Ti"
      End Sub
    
      Dim Zufall As New System.Random
      Dim ds As New DataTable("tblDaten")
      Public Sub testChart01() Handles TextBox.MouseDown
        Dim row As DataRow
        Dim d As New DateTime
        Dim z As Int16 = 0
        With Me
          .TextBox.Text = "Start"
          For i As Integer = 0 To 200
            .TextBox.Text = "    i=" & i.ToString("00") & "  Anzahl Daten=" & ds.Rows.Count
            row = ds.NewRow()
            row("Zeit") = z
            z = CType(z + 1, Short)
            row("T") = Zufall.NextDouble
            row("Ti") = Zufall.NextDouble
            ds.Rows.Add(row)
          Next
          .Chart.DataSource = Nothing
          .Chart.DataSource = ds
          .Chart.Invalidate()
        End With
    
      End Sub
    
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 2. Mai 2018 11:09
  • Hi,

    in deinem Fall (zumindest im Beispiel) ist "Chart.Invalidate()" nicht ganz das richtige. Nimm "Chart.DataBind()", damit funktioniert (dein Beispiel).

    Ein kleiner Tip am Rande; die Namensgebung deiner Controls ist eher ungünstig. "Chart" und "TextBox" sind Typen, deine Controls sollten so nicht heißen.

    Gruß, Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    • Als Antwort markiert Hannebambel Mittwoch, 2. Mai 2018 11:48
    Mittwoch, 2. Mai 2018 11:11
  • ahhhh, funzt!

    Danke

    Das vorliegende Beispiel ist nur eine Bastelei, um die grundlegenden Funktionen von .NET mal zu verstehen. Die spätere Anwendung wird dann "systematischer". Das hier ist quick'n dirty.

    Und dieses "Strict On" ist ja sowas von restriktiv! ;-) da darf man ja gar nix mehr!

    H.

    Mittwoch, 2. Mai 2018 11:22
  • Und dieses "Strict On" ist ja sowas von restriktiv! ;-) da darf man ja gar nix mehr!

    Ich behaupte aus eigener Erfahrung, dass man mit Option Strict Off kein stabiles Programm bekommt.

    Option Strict Off
    Module Module1
      Sub Main()
        Dim a1 = "1"
        Dim a2 = "2"
        Dim res1 = a1 + a2
        Console.WriteLine(res1)
        Dim res2 As String = a1 + Integer.Parse(a2)
        Console.WriteLine(res2)
        Console.WriteLine("weiter mit Taste")
        Console.ReadKey()
      End Sub
    End Module



    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 2. Mai 2018 11:37
  • na ja, man kann das Ganze natürlich auch forcieren. In deinem Beispiel arbeitest du mit "Variant", was ja alles sein darf.

    Früher hat man mit FORTRAN auch was hinbekommen, ohne Variablendeklaration oder automatischer Initialisierung mit 'nem Standardwert.

    Aber, ich stimme durchaus zu, dass man das ein oder andere Problemchen umgehen kann, wenn man auf Strict On geht. Ich bin nur immer wieder erstaunt, wo diese Option meckert, wo es "früher" überhaupt keinen Anlass zum Nachdenken gab. Ich bin's (noch) nicht gewöhnt!

    Mittwoch, 2. Mai 2018 11:48
  • Variant gibt es im VB.NET nicht mehr.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 2. Mai 2018 12:41