Benutzer mit den meisten Antworten
Chart mit Daten füllen

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
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
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 -
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
-
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.
-
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 -
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!
-
Variant gibt es im VB.NET nicht mehr.
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks