using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;
namespace loading
{
public partial class _11111111 : Form
{
private bool isopen = false;
// 绘图相关变量
private List<PointF> dataPoints = new List<PointF>();
private Pen axisPen = new Pen(Color.Black, 2);
private Pen gridPen = new Pen(Color.LightGray, 1) { DashStyle = DashStyle.Dash };
private Pen dataPen = new Pen(Color.Red, 2);
private Font axisFont = new Font("Arial", 8);
private SolidBrush textBrush = new SolidBrush(Color.Black);
private SolidBrush pointBrush = new SolidBrush(Color.Blue);
private int padding = 40; // 坐标系边距
private StringBuilder serialBuffer = new StringBuilder(); // 串口数据缓冲区
public _11111111()
{
InitializeComponent();
InitializeDrawingPanel();
}
private void InitializeDrawingPanel()
{
// 启用双缓冲(通过反射)
typeof(Panel).InvokeMember("DoubleBuffered",
BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, drawingPanel, new object[] { true });
drawingPanel.Paint += DrawingPanel_Paint;
drawingPanel.SizeChanged += (s, e) =>
{
drawingPanel.Invalidate();
};
}
private void DrawingPanel_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
if (drawingPanel.Width <= 0 || drawingPanel.Height <= 0) return;
// 1. 绘制坐标系(原点在左中位置,显示第一和第二象限)
DrawCoordinateSystem(g);
// 2. 绘制数据点(如果有数据)
if (dataPoints.Count > 0)
{
DrawDataPoints(g);
}
// 3. 绘制调试信息
DrawDebugInfo(g);
}
// 修复后的坐标系绘制(显示第一和第二象限)
private void DrawCoordinateSystem(Graphics g)
{ // 原点定位到面板中心(实现对称分布)
int originX = drawingPanel.Width / 2;
int originY = drawingPanel.Height / 2;
// 计算动态可用区域
int axisWidth = drawingPanel.Width - padding * 2;
int axisHeight = drawingPanel.Height - padding * 2;
// 绘制X轴(居中延伸)
g.DrawLine(axisPen,
originX - axisWidth / 2, originY,
originX + axisWidth / 2, originY);
// 绘制Y轴(居中延伸)
g.DrawLine(axisPen,
originX, originY - axisHeight / 2,
originX, originY + axisHeight / 2);
// 绘制箭头
DrawArrow(g, new Point(originX + axisWidth / 2, originY), Direction.Right); // X轴正方向
DrawArrow(g, new Point(originX - axisWidth / 2, originY), Direction.Left); // X轴负方向
DrawArrow(g, new Point(originX, originY - axisHeight), Direction.Up); // Y轴正方向
// 绘制原点标记
g.DrawString("0", new Font(axisFont, FontStyle.Bold), Brushes.Red, originX - 15, originY + 5);
// 绘制网格和刻度
DrawGrid(g, originX, originY, axisWidth, axisHeight);
}
// 修复后的网格绘制(显示第一和第二象限)
private void DrawGrid(Graphics g, int originX, int originY, int axisWidth, int axisHeight)
{
// X轴网格数量(左右各5个)
int gridCountX = 10;
// Y轴网格数量
int gridCountY = 10;
// 计算每个网格的宽度和高度
float gridSizeX = axisWidth / (float)gridCountX;
float gridSizeY = axisHeight / (float)gridCountY;
// 绘制横向网格(只向上)
for (int i = 1; i <= gridCountY; i++)
{
int yPos = originY - (int)(i * gridSizeY);
if (yPos < 0) continue; // 确保不超出顶部
g.DrawLine(gridPen, originX - axisWidth / 2, yPos, originX + axisWidth / 2, yPos);
g.DrawString($"{i}", axisFont, textBrush, originX - 25, yPos - 8);
}
// 绘制纵向网格(左右各5个)
for (int i = 1; i <= gridCountX / 2; i++)
{
// 右侧网格
int xPosRight = originX + (int)(i * gridSizeX);
g.DrawLine(gridPen, xPosRight, originY, xPosRight, originY - axisHeight);
g.DrawString($"{i}", axisFont, textBrush, xPosRight - 5, originY + 5);
// 左侧网格
int xPosLeft = originX - (int)(i * gridSizeX);
g.DrawLine(gridPen, xPosLeft, originY, xPosLeft, originY - axisHeight);
g.DrawString($"-{i}", axisFont, textBrush, xPosLeft - 15, originY + 5);
}
// 绘制坐标轴标签
g.DrawString("X轴", axisFont, textBrush, originX + axisWidth / 2 - 20, originY + 20);
g.DrawString("Y轴", axisFont, textBrush, originX - 30, originY - axisHeight);
}
// 修复后的数据点绘制(显示第一和第二象限)
private void DrawDataPoints(Graphics g)
{
if (dataPoints.Count == 0) return;
// 设置原点在左中位置
int originX = padding;
int originY = drawingPanel.Height - padding;
int axisWidth = drawingPanel.Width - padding * 2;
int axisHeight = drawingPanel.Height - padding * 2;
// 计算数据范围(X轴正负,Y轴正方向)
float maxX = 1.0f, maxY = 1.0f, minX = -1.0f;
foreach (var point in dataPoints)
{
if (Math.Abs(point.X) > maxX) maxX = Math.Abs(point.X);
if (point.Y > maxY) maxY = point.Y;
if (point.X < minX) minX = point.X;
}
// 确保最小值
maxX = Math.Max(maxX, 1.0f);
maxY = Math.Max(maxY, 1.0f);
// 计算缩放比例
float scaleX = axisWidth / (maxX - minX); // X轴范围从minX到maxX
float scaleY = axisHeight / maxY;
// 绘制数据点和连线
PointF? prevPoint = null;
foreach (var point in dataPoints)
{
// 确保Y>=0
float validY = Math.Max(0, point.Y);
// 坐标转换
float screenX = originX + (point.X - minX) * scaleX;
float screenY = originY - validY * scaleY;
// 只绘制上半部分的点
if (screenY < 0) continue;
// 绘制数据点
g.FillEllipse(pointBrush, screenX - 3, screenY - 3, 6, 6);
// 连接线
if (prevPoint != null)
{
g.DrawLine(dataPen, prevPoint.Value.X, prevPoint.Value.Y, screenX, screenY);
}
prevPoint = new PointF(screenX, screenY);
// 调试输出
Debug.WriteLine($"点({point.X},{point.Y}) -> 屏幕({screenX},{screenY})");
}
}
// 添加调试信息
private void DrawDebugInfo(Graphics g)
{
g.DrawString($"数据点数量: {dataPoints.Count}",
axisFont, Brushes.Blue, 10, 10);
if (dataPoints.Count > 0)
{
var lastPoint = dataPoints.Last();
g.DrawString($"最新点: ({lastPoint.X:F2}, {lastPoint.Y:F2})",
axisFont, Brushes.Blue, 10, 30);
}
}
// 修改后的箭头绘制
private void DrawArrow(Graphics g, Point point, Direction direction)
{
Point[] arrowPoints;
int size = 8;
switch (direction)
{
case Direction.Up:
arrowPoints = new Point[] {
point,
new Point(point.X - size, point.Y + size),
new Point(point.X + size, point.Y + size)
};
break;
case Direction.Right:
arrowPoints = new Point[] {
point,
new Point(point.X - size, point.Y - size),
new Point(point.X - size, point.Y + size)
};
break;
default:
return;
}
g.FillPolygon(Brushes.Black, arrowPoints);
}
private enum Direction { Up, Right, Left}
// 打开串口
private void open_btn_Click(object sender, EventArgs e)
{
try
{
if (serialPort2.IsOpen == false)
{
serialPort2.PortName = port_cbb.Text;
serialPort2.BaudRate = Convert.ToInt32(baud_cbb.Text);
serialPort2.Open();
isopen = true;
open_btn.Text = "关闭串口";
statusLabel.Text = $"已打开串口: {port_cbb.Text}@{baud_cbb.Text}";
// 添加串口数据接收处理
serialPort2.DataReceived += SerialPort2_DataReceived;
}
else
{
serialPort2.Close();
isopen = false;
open_btn.Text = "打开串口";
statusLabel.Text = "串口已关闭";
// 移除串口数据接收处理
serialPort2.DataReceived -= SerialPort2_DataReceived;
}
}
catch (Exception ex)
{
statusLabel.Text = $"串口操作失败: {ex.Message}";
}
}
// 串口数据接收事件
private void SerialPort2_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
// 读取所有可用数据
int bytesToRead = serialPort2.BytesToRead;
byte[] buffer = new byte[bytesToRead];
serialPort2.Read(buffer, 0, bytesToRead);
// 将字节转换为字符串
string data = Encoding.ASCII.GetString(buffer);
// 添加到缓冲区
serialBuffer.Append(data);
// 处理缓冲区中的完整行
ProcessSerialBuffer();
}
catch (Exception ex)
{
// 在UI线程显示错误
this.Invoke((MethodInvoker)delegate {
statusLabel.Text = $"接收错误: {ex.Message}";
});
}
}
// 处理串口缓冲区中的数据
private void ProcessSerialBuffer()
{
// 检查是否有完整行
while (serialBuffer.ToString().Contains("\n"))
{
int newLineIndex = serialBuffer.ToString().IndexOf('\n');
string line = serialBuffer.ToString(0, newLineIndex).Trim();
serialBuffer.Remove(0, newLineIndex + 1);
if (!string.IsNullOrEmpty(line))
{
// 在UI线程处理数据
this.Invoke((MethodInvoker)delegate {
ProcessIncomingData(line);
});
}
}
}
// 处理接收到的数据
private void ProcessIncomingData(string data)
{
// 更新状态栏显示原始数据
statusLabel.Text = $"接收: {data}";
try
{
// 示例数据格式: "X123.45,Y67.89" 或 "123.45,67.89"
if (data.Contains(","))
{
string[] parts = data.Split(',');
if (parts.Length >= 2)
{
float x, y;
// 尝试解析带前缀的格式
if (parts[0].StartsWith("X") || parts[0].StartsWith("x"))
{
if (!float.TryParse(parts[0].Substring(1), out x)) return;
if (!float.TryParse(parts[1].Substring(1), out y)) return;
}
else // 直接数值格式
{
if (!float.TryParse(parts[0], out x)) return;
if (!float.TryParse(parts[1], out y)) return;
}
// 添加到数据点集合
dataPoints.Add(new PointF(x, y));
// 限制数据点数量
if (dataPoints.Count > 100)
dataPoints.RemoveAt(0);
// 重绘面板
drawingPanel.Invalidate();
// 更新状态
statusLabel.Text = $"点({x}, {y}) 已添加";
}
}
else
{
statusLabel.Text = $"无效数据格式: {data}";
}
}
catch (Exception ex)
{
statusLabel.Text = $"解析错误: {ex.Message}";
}
}
private void _11111111_Load(object sender, EventArgs e)
{
serialLoad();
// 初始化波特率下拉框
baud_cbb.Items.AddRange(new object[] { 9600, 19200, 38400, 57600, 115200 });
baud_cbb.SelectedIndex = 0;
// 添加测试数据
AddTestData(0, 0);
AddTestData(50, 50);
AddTestData(-50, 30);
}
// 添加数据点
public void AddTestData(float x, float y)
{
dataPoints.Add(new PointF(x, y));
drawingPanel.Invalidate();
}
private void serialLoad()
{
try
{
RegistryKey keyCom = Registry.LocalMachine.OpenSubKey(@"Hardware\DeviceMap\SerialComm");
if (keyCom != null)
{
string[] sSubKeys = keyCom.GetValueNames();
port_cbb.Items.Clear();
foreach (var sValue in sSubKeys)
{
string portName = (string)keyCom.GetValue(sValue);
if (!string.IsNullOrEmpty(portName))
port_cbb.Items.Add(portName);
}
// 默认选择第一个可用端口
if (port_cbb.Items.Count > 0)
port_cbb.SelectedIndex = 0;
}
}
catch (Exception ex)
{
statusLabel.Text = $"加载串口失败: {ex.Message}";
}
}
// 清除数据按钮
private void btnClear_Click(object sender, EventArgs e)
{
dataPoints.Clear();
drawingPanel.Invalidate();
statusLabel.Text = "数据已清除";
}
// 窗体关闭时关闭串口
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (serialPort2.IsOpen)
{
serialPort2.Close();
}
}
// 其他事件处理(如标签点击事件)
private void label2_Click(object sender, EventArgs e) { }
private void label1_Click(object sender, EventArgs e) { }
private void drawingPanel_Paint_1(object sender, PaintEventArgs e)
{
}
}
}根据我的代码整合
最新发布