使用串行端口数据的实时draw.lines

时间:2018-06-01 13:30:54

标签: c# winforms plot serial-port drawing

我希望我的简单程序从串口获取X和Y坐标并在窗口中绘制它们(就像绘画一样,但是除了鼠标之外的其他设备)。 我设法创建了重新编码和转换数据的代码,但我无法处理在表单上绘制数据。

程序一直有效,直到Form1窗口出现。然后我只在控制台中收到“data_recived”和数据值,但是其他的datarecived事件都没有执行。

我知道DataReceivedHandler有问题,但我尝试了很多解决方案,但没有一个能够正常工作。 (在评论中你可以看到我尝试使用计时器trigerred事件来做到这一点)。

至少有人能给我一些如何解决问题的提示吗?我真的很感激

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO.Ports;
using System.Threading;


namespace WindowsFormsApp1
{
  public partial class Form1 : Form
  {

    public string data;
    private List<Point> points; 

    private Bitmap bmp; 
    private Pen pen;
    private PictureBox pictureBox1 = new PictureBox();

    //private System.Timers.Timer _timer;
    //private DateTime _startTime;

    public Form1()
    {
        InitializeComponent();

        SerialPort serialPort1 = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        serialPort1.Open();
        serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        DoubleBuffered = true; 

        pen = new Pen(Color.Black, 3);

        points = new List<Point>();

      //  _startTime = DateTime.Now;
       // _timer = new System.Timers.Timer(100); // 0.1 s
       // _timer.Elapsed += new System.Timers.ElapsedEventHandler (timer_Elapsed);
       // _timer.Start();
      //  Console.WriteLine("Czas Start");
    }


    public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        SerialPort serialPort1 = (SerialPort)sender;
        Console.WriteLine("data_recived");
        data = serialPort1.ReadLine();
        Console.WriteLine(data);

        pointlist_reciver();

    }

   // void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    //{
    //    Console.WriteLine("Czas");
        // TimeSpan timeSinceStart = DateTime.Now - _startTime;
        //string output = string.Format("{0},{1}\r\n", DateTime.Now.ToLongDateString(), (int)Math.Floor(timeSinceStart.TotalMinutes));
   //     pointlist_reciver();
   // }

    public void pointlist_reciver()

    {

                int x1;
                int y1;
                points = new List<Point>();
                string[] coordinates = new string[2];
                coordinates = data.Split(',');
                string x = coordinates[0];
                string y = coordinates[1];
                Int32.TryParse(x, out x1);
                Int32.TryParse(y, out y1);
                points.Add(new Point(x1, y1));

                if (points.Count >= 2)
                {
                     this.Paint += new PaintEventHandler(Form1_Paint);
                }

    }
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        PaintP(e);
    }

    public void PaintP ( PaintEventArgs e)
    {
        bmp = new Bitmap(1500, 1500); 
        using (Graphics g = Graphics.FromImage(bmp))
            g.Clear(Color.White);
        e.Graphics.DrawLines(pen, points.ToArray()); 
        points.Clear();
    }
  }
}

2 个答案:

答案 0 :(得分:2)

points.Count >= 2

永远不会发生

this.Paint += new PaintEventHandler(Form1_Paint)

这在这里没有意义,你需要在表单加载时只注册一次。您要找的是Invalidate()。请注意,您可能处于不同的线程,因此可能需要先调用。

bmp = new Bitmap(1500, 1500); 
using (Graphics g = Graphics.FromImage(bmp))
    g.Clear(Color.White);
e.Graphics.DrawLines(pen, points.ToArray()); 
points.Clear();

您创建甚至不使用的位图。不确定你到底想要达到的目标。

示例

您有两种选择。您可以在位图上绘制并在表单上粘贴该位图。或者你只是在表格上画画。我做了一个简单的例子,说明如何使用后一个选项。当您在表单上移动鼠标时,它会绘制点。只需注册eventhandlers - Load,MouseMove,Paint。

List<Point> points = new List<Point>();

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    points.Add(e.Location);
    Invalidate();
}

private void Form1_Load(object sender, EventArgs e)
{
    this.DoubleBuffered = true;
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
    int radius = 3;
    for (int i = points.Count - 1; i >= 0; --i)
    {
        Point p = points[i];

        p.Y += 1;
        if (p.Y > Height)
        {
            points.RemoveAt(i);
            continue;
        }
        points[i] = p;

        e.Graphics.FillEllipse(
            Brushes.Red,
            p.X - radius,
            p.Y - radius,
            2 * radius,
            2 * radius
            );
    }
}

答案 1 :(得分:0)

由于您的建议,我设法使我的代码工作。它仍然需要一些工作,因为它绘制了单独的线而不是连续的线。

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO.Ports;
using System.Threading;


namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {

    public string data;
    private List<Point> points = new List<Point>();  
    public string[] coordinates;
    private Pen pen;
    public Bitmap obrazek;
    public int i = 0;

    public Form1()
    {
        InitializeComponent();

        obrazek = new Bitmap(1000, 1000); 
        using (Graphics g = Graphics.FromImage(obrazek))
        g.Clear(Color.White); 

        SerialPort serialPort1 = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        serialPort1.Open();
        serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        DoubleBuffered = true;

        pen = new Pen(Color.Black, 3);

        points = new List<Point>();

    }


    public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {

        SerialPort TempSerialPort = (SerialPort)sender;
        //Console.WriteLine("data_recived");
        data = TempSerialPort.ReadLine();
        Console.WriteLine(data);
        pointlist_reciver();
        //this.Invalidate();
        pictureBox2.Invalidate();



    }


    public void pointlist_reciver()

    {

        int x1;
        int y1;
        string[] coordinates = data.Split(',');
        string x = coordinates[0];
        string y = coordinates[1];
        Int32.TryParse(x, out x1);
        Int32.TryParse(y, out y1);
        points.Add(new Point(x1, y1));
        Console.WriteLine(points.Count.ToString());

    }
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawImage(obrazek, 0, 0);

        if (points.Count >= 2)
        {

            List<Point> points2 = points.GetRange(0, 2);
            using (Graphics g = Graphics.FromImage(obrazek)) 
            g.DrawLines(pen, points2.ToArray());
            points.Clear();

        }
    }
 }

}

稍后我将发布最终版本。