我希望我的简单程序从串口获取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();
}
}
}
答案 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();
}
}
}
}
稍后我将发布最终版本。