Draw.lines в реальном времени с использованием данных последовательного порта - PullRequest
0 голосов
/ 01 июня 2018

Я хочу, чтобы моя простая программа брала координаты X и Y из последовательного порта и рисовала их в окне (как рисование, но с использованием другого устройства, кроме мыши).Мне удалось создать код, который получает и преобразовывает данные, однако я не могу обрабатывать рисование этих данных в форме.

Программа работает, пока не появится окно Form1.Затем я получаю только «data_recived» и значение данных в консоли, но остальные события datarecived не выполняются.

Я знаю, что с DataReceivedHandler что-то не так, но я пробовал так много решений, и ни одно из них не сработало.(в комментариях вы можете увидеть мои попытки использовать для этого таймерное событие).

Может кто-нибудь дать мне хотя бы несколько советов, как решить мою проблему?Я был бы очень благодарен

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 голосов
/ 03 июня 2018

Мне удалось заставить мой код работать благодаря вашим предложениям.Это все еще нуждается в некоторой работе, потому что это рисует отдельные линии вместо непрерывных.

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();

        }
    }
 }

}

Позже я опубликую окончательную версию.

0 голосов
/ 01 июня 2018

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();

вы создаете растровое изображение, которое вы даже не используете.Не уверен, что именно вы пытаетесь достичь здесь.

Пример

У вас есть два варианта.Либо вы рисуете на растровом изображении и вставляете это растровое изображение в форму.Или вы просто рисуете на форме.Я сделал простой пример, как использовать последний вариант.Когда вы перемещаете мышь по форме, она рисует точки.Просто зарегистрируйте обработчики событий - 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
            );
    }
}
...