Laden...

Messwerte als Graph darstellen?

Erstellt von haseluenne vor 17 Jahren Letzter Beitrag vor 16 Jahren 7.217 Views
H
haseluenne Themenstarter:in
7 Beiträge seit 2006
vor 17 Jahren
Messwerte als Graph darstellen?

Hallo, ich würde gerne die Werte einer laufenden Messung nebenbei als (weiter wandernden) Graph darstellen, so wie die CPU-Auslastung im Task-Manager.
z.B.

Die zed-lib ist dafür wohl überdimensioniert/für etwas anderes gedacht.
was gibt es da sonst an fertigen Lösungen?

2.921 Beiträge seit 2005
vor 17 Jahren

zeichne das doch mit DrawLine. Punkt array merken. Dann scrollen (einfach Versatz der Grafik ausrechnen, d.h. in diesem Falle ganz einfach im Array an einem anderen Index anfangen und neuzeichnen)

Wenn es zu unverständlich sein sollte, erläutere ich das gerne noch einmal genauer.

Dafür brauchst du keine Lib.

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.

5.658 Beiträge seit 2006
vor 17 Jahren

Würde mich auch interessieren, besonders der Teil bei dem die Linien (neu)gezeichnet werden. Das macht man bestimmt mit GDI, oder?

Weeks of programming can save you hours of planning

2.921 Beiträge seit 2005
vor 17 Jahren

ok, hier bitteschön:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MessungsGraph
{
    public partial class Form1 : Form
    {
        List<Point> m_aPoint = new List<Point>();
        Timer m_Timer = new Timer();
        Random random = new Random((int)DateTime.Now.Ticks);
        CustomPanel panel1 = new CustomPanel();
        public Form1()
        {
            InitializeComponent();
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            for (int i = 0; i < panel1.Width / 2; i += 2)
            {
                this.panel1.Points.Add(new Point(0,random.Next(0,panel1.Height)));
            }
            m_Timer.Tick += new EventHandler(m_Timer_Tick);
            m_Timer.Interval = 20;
            m_Timer.Start();
            panel1.Bounds = this.Bounds;
            panel1.Parent = this;
            panel1.Dock = DockStyle.Fill;
        }

        void m_Timer_Tick(object sender, EventArgs e)
        {
            if (this.panel1.Points.Count > 0)
            {
                this.panel1.Points.RemoveAt(0);
            }
            this.panel1.Points.Add(new Point(0,random.Next(0,panel1.Height)));
            panel1.Invalidate();
        }
    }
}

Das hier ist die Hauptroutine, wenn wir einen Timer-Tick-Event erhalten, löschen wir den 1. Punkt und fügen einen neuen hinzu. Jetzt müssen wir uns schon nicht mehr um das scrollen, sondern nur noch um das neuzeichnen kümmern.

Da die Control (In diesem Falle das Panel) die Anzeige übernehmen soll,
leiten wir es von Panel ab und können somit DoubleBuffered = true setzen ohne Reflection o. ä. Tricks benutzen zu müssen.

Das Panel enhtält die Punkte Liste und eine Schleife zum Zeichnen der Punkte:


using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace MessungsGraph
{
    class CustomPanel:Panel
    {
        private List<Point> m_aPoint = new List<Point>();
        private int m_nDelta = 0;
        public CustomPanel()
        {
            this.DoubleBuffered = true;
            this.BackColor = Color.Black;
        }

        public List<Point> Points
        {
            get { return this.m_aPoint; }
        }

        protected override void OnResize(EventArgs eventargs)
        {
            m_nDelta = this.Width / this.m_aPoint.Count;
            base.OnResize(eventargs);
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            for (int i = 0; i < this.m_aPoint.Count - 1; i++)
            {
                e.Graphics.DrawLine(Pens.Blue, new Point(m_nDelta*i, this.m_aPoint[i].Y), new Point(m_nDelta*i+m_nDelta, this.m_aPoint[i + 1].Y));
            }
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            e.Graphics.FillRectangle(new SolidBrush(this.BackColor), e.ClipRectangle);
        }
    }
}

Ausserdem enthält es ein "m_nDelta", das beim Resizen neu berechnet wird.
Probiert es aus, sogar beim Skalieren wird korrekt weitergezeichnet.

Hier das Testprojekt dazu:

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.

V
142 Beiträge seit 2006
vor 17 Jahren

Hi,

Wieso nimmst nicht Dundas Charts?

Mit den Dingern kann man relativ einfach Graphen jeglicher Art machen. Habe auch mal den CPU Verlauf nachprogrammiert mit so einem Ding. Das ganze hat villeicht 10 min gedauert 🙂.

Ich weiß leider nicht mehr welchen von diesen Charts ich dafür genommen habe, aber wenn es dich interessiert kann ich mal nachschauen.

2.921 Beiträge seit 2005
vor 17 Jahren

Wieso soll er jetzt etwas kaufen, das hiermit eigentlich schon gelöst ist!?

Na, das müßt ihr wissen.

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.

H
haseluenne Themenstarter:in
7 Beiträge seit 2006
vor 16 Jahren

Soo, bin nun endlich mal dazu gekommen mit dem Projekt weiterzumachen.

Danke @Dragon, hilft mir super weiter. Hab aber jetzt noch mal ein Problem (bin ja noch recht neu in OOP, hab wohl irgendwas nicht richtig bekannt gemacht...).

Jedenfalls wollte ich die Funktion die die Werte generiert jetzt mal auslagern (ganz am Ende, die Funktion "Zahlgenerator", jedoch bekomme ich folgende Fehler:

Fehler	1	Die beste Übereinstimmung für die überladene System.Drawing.Point.Point(int, int)-Methode hat einige ungültige Argumente.	C:\Dokumente und Einstellungen\Sebastian\Desktop\messungsgraph\MessungsGraph\MessungsGraph\Form1.cs	40	36	MessungsGraph
Fehler	2	2-Argument: kann nicht von "Methodengruppe" in "int" konvertiert werden.	C:\Dokumente und Einstellungen\Sebastian\Desktop\messungsgraph\MessungsGraph\MessungsGraph\Form1.cs	40	48	MessungsGraph

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MessungsGraph
{
    public partial class Form1 : Form
    {
        List<Point> m_aPoint = new List<Point>();
        Timer m_Timer = new Timer();
        Random random = new Random((int)DateTime.Now.Ticks);
        CustomPanel panel1 = new CustomPanel();
        public Form1()
        {
            InitializeComponent();
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            for (int i = 0; i < panel1.Width / 2; i += 2)
            {
                this.panel1.Points.Add(new Point(0,random.Next(0,panel1.Height)));
            }
            m_Timer.Tick += new EventHandler(m_Timer_Tick);
            m_Timer.Interval = 20;
            m_Timer.Start();
            panel1.Bounds = this.Bounds;
            panel1.Parent = this;
            panel1.Dock = DockStyle.Fill;
        }

        void m_Timer_Tick(object sender, EventArgs e)
        {
            if (this.panel1.Points.Count > 0)
            {
                this.panel1.Points.RemoveAt(0);
            }
            this.panel1.Points.Add(new Point(0,zahlgenerator));
            panel1.Invalidate();
        }

      [b]  public int zahlgenerator()
        {
            return random.Next(0, panel1.Height);

        }
[/b]


    }
}
G
58 Beiträge seit 2007
vor 16 Jahren
this.panel1.Points.Add(new Point(0,zahlgenerator));

fällt dir auf, dass da zwei Klammern fehlen? 😁
nebenbei, warum verwendest du die Funktion in m_Timer_Tick aber nicht im Konstruktur?

H
haseluenne Themenstarter:in
7 Beiträge seit 2006
vor 16 Jahren

Hallo,
sry, mir fällt da nix auf 😄. hab genau so das Projekt von dort oben genommen (lief auch wunderbar) und lediglich aus

 void m_Timer_Tick(object sender, EventArgs e)
        {
            if (this.panel1.Points.Count > 0)
            {
                this.panel1.Points.RemoveAt(0);
            }
            this.panel1.Points.Add(new Point(0,random.Next(0, panel1.Height)));
            panel1.Invalidate();
        }

das gemacht was ich vorher gepostet hab, also den Zufallsgenerator in eine Funktion ausgelagert, deren Rückgabewert der Zufallswert ist (oder besser: sein sollte.. 🤔 )