using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;
using ScottPlot;
using System.IO;
namespace PhysicsExperimentDisplay
{
// 关键修复1:添加partial修饰符
public partial class MainForm : Form
{
// 控件声明
private TableLayoutPanel mainLayout;
private GroupBox gbSerial;
private ComboBox cmbPorts;
private ComboBox cmbBaudRate;
private Button btnConnect;
private Label lblPort;
private Label lblBaud;
private GroupBox gbData;
private DataGridView dgvResults;
private GroupBox gbChart;
private FormsPlot formsPlot;
private Button btnExport;
private Button btnClear;
private SerialPort serialPort;
private FlowLayoutPanel buttonPanel;
// 数据存储
private List<double> accelerationData = new List<double>();
private TableLayoutPanel serialLayout;
private DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
private DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
private DataGridViewTextBoxColumn dataGridViewTextBoxColumn3;
private DataGridViewTextBoxColumn dataGridViewTextBoxColumn4;
private DataGridViewTextBoxColumn dataGridViewTextBoxColumn5;
private DataGridViewTextBoxColumn dataGridViewTextBoxColumn6;
private int dataPointCount = 0;
public MainForm()
{
// 关键修复2:确保只有一个InitializeComponent调用
InitializeComponent();
LoadAvailablePorts();
}
// 关键修复3:明确的InitializeComponent实现
private void InitializeComponent()
{
this.mainLayout = new System.Windows.Forms.TableLayoutPanel();
this.gbSerial = new System.Windows.Forms.GroupBox();
this.serialLayout = new System.Windows.Forms.TableLayoutPanel();
this.lblPort = new System.Windows.Forms.Label();
this.cmbPorts = new System.Windows.Forms.ComboBox();
this.lblBaud = new System.Windows.Forms.Label();
this.cmbBaudRate = new System.Windows.Forms.ComboBox();
this.btnConnect = new System.Windows.Forms.Button();
this.buttonPanel = new System.Windows.Forms.FlowLayoutPanel();
this.btnExport = new System.Windows.Forms.Button();
this.btnClear = new System.Windows.Forms.Button();
this.gbData = new System.Windows.Forms.GroupBox();
this.dgvResults = new System.Windows.Forms.DataGridView();
this.gbChart = new System.Windows.Forms.GroupBox();
this.formsPlot = new ScottPlot.FormsPlot();
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.mainLayout.SuspendLayout();
this.gbSerial.SuspendLayout();
this.serialLayout.SuspendLayout();
this.buttonPanel.SuspendLayout();
this.gbData.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvResults)).BeginInit();
this.gbChart.SuspendLayout();
this.SuspendLayout();
//
// mainLayout
//
this.mainLayout.ColumnCount = 1;
this.mainLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.mainLayout.Controls.Add(this.gbSerial, 0, 0);
this.mainLayout.Controls.Add(this.buttonPanel, 0, 1);
this.mainLayout.Controls.Add(this.gbData, 0, 2);
this.mainLayout.Controls.Add(this.gbChart, 0, 3);
this.mainLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainLayout.Location = new System.Drawing.Point(0, 0);
this.mainLayout.Name = "mainLayout";
this.mainLayout.RowCount = 4;
this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 100F));
this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40F));
this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 60F));
this.mainLayout.Size = new System.Drawing.Size(1178, 744);
this.mainLayout.TabIndex = 0;
//
// gbSerial
//
this.gbSerial.Controls.Add(this.serialLayout);
this.gbSerial.Dock = System.Windows.Forms.DockStyle.Fill;
this.gbSerial.Location = new System.Drawing.Point(10, 10);
this.gbSerial.Margin = new System.Windows.Forms.Padding(10);
this.gbSerial.Name = "gbSerial";
this.gbSerial.Size = new System.Drawing.Size(1158, 80);
this.gbSerial.TabIndex = 0;
this.gbSerial.TabStop = false;
this.gbSerial.Text = "串口设置";
//
// serialLayout
//
this.serialLayout.ColumnCount = 4;
this.serialLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F));
this.serialLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F));
this.serialLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F));
this.serialLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F));
this.serialLayout.Controls.Add(this.lblPort, 0, 0);
this.serialLayout.Controls.Add(this.cmbPorts, 1, 0);
this.serialLayout.Controls.Add(this.lblBaud, 2, 0);
this.serialLayout.Controls.Add(this.cmbBaudRate, 3, 0);
this.serialLayout.Controls.Add(this.btnConnect, 0, 1);
this.serialLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.serialLayout.Location = new System.Drawing.Point(3, 29);
this.serialLayout.Name = "serialLayout";
this.serialLayout.RowCount = 2;
this.serialLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.serialLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.serialLayout.Size = new System.Drawing.Size(1152, 48);
this.serialLayout.TabIndex = 0;
//
// lblPort
//
this.lblPort.Location = new System.Drawing.Point(3, 0);
this.lblPort.Name = "lblPort";
this.lblPort.Size = new System.Drawing.Size(94, 20);
this.lblPort.TabIndex = 0;
this.lblPort.Text = "串口号:";
this.lblPort.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// cmbPorts
//
this.cmbPorts.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbPorts.Font = new System.Drawing.Font("Consolas", 10F);
this.cmbPorts.Location = new System.Drawing.Point(103, 3);
this.cmbPorts.Name = "cmbPorts";
this.cmbPorts.Size = new System.Drawing.Size(121, 31);
this.cmbPorts.TabIndex = 1;
//
// lblBaud
//
this.lblBaud.Location = new System.Drawing.Point(579, 0);
this.lblBaud.Name = "lblBaud";
this.lblBaud.Size = new System.Drawing.Size(94, 20);
this.lblBaud.TabIndex = 2;
this.lblBaud.Text = "波特率:";
this.lblBaud.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// cmbBaudRate
//
this.cmbBaudRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbBaudRate.Font = new System.Drawing.Font("Consolas", 10F);
this.cmbBaudRate.Location = new System.Drawing.Point(679, 3);
this.cmbBaudRate.Name = "cmbBaudRate";
this.cmbBaudRate.Size = new System.Drawing.Size(121, 31);
this.cmbBaudRate.TabIndex = 3;
//
// btnConnect
//
this.btnConnect.BackColor = System.Drawing.Color.LightGreen;
this.serialLayout.SetColumnSpan(this.btnConnect, 4);
this.btnConnect.Dock = System.Windows.Forms.DockStyle.Fill;
this.btnConnect.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F, System.Drawing.FontStyle.Bold);
this.btnConnect.Location = new System.Drawing.Point(20, 25);
this.btnConnect.Margin = new System.Windows.Forms.Padding(20, 5, 20, 5);
this.btnConnect.Name = "btnConnect";
this.btnConnect.Size = new System.Drawing.Size(1112, 18);
this.btnConnect.TabIndex = 4;
this.btnConnect.Text = "连接串口";
this.btnConnect.UseVisualStyleBackColor = false;
//
// buttonPanel
//
this.buttonPanel.Controls.Add(this.btnExport);
this.buttonPanel.Controls.Add(this.btnClear);
this.buttonPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.buttonPanel.Location = new System.Drawing.Point(3, 103);
this.buttonPanel.Name = "buttonPanel";
this.buttonPanel.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0);
this.buttonPanel.Size = new System.Drawing.Size(1172, 34);
this.buttonPanel.TabIndex = 1;
//
// btnExport
//
this.btnExport.BackColor = System.Drawing.Color.LightBlue;
this.btnExport.Location = new System.Drawing.Point(13, 3);
this.btnExport.Name = "btnExport";
this.btnExport.Size = new System.Drawing.Size(150, 35);
this.btnExport.TabIndex = 0;
this.btnExport.Text = "导出数据(CSV)";
this.btnExport.UseVisualStyleBackColor = false;
//
// btnClear
//
this.btnClear.BackColor = System.Drawing.Color.LightSalmon;
this.btnClear.Location = new System.Drawing.Point(169, 3);
this.btnClear.Name = "btnClear";
this.btnClear.Size = new System.Drawing.Size(150, 35);
this.btnClear.TabIndex = 1;
this.btnClear.Text = "清除数据";
this.btnClear.UseVisualStyleBackColor = false;
//
// gbData
//
this.gbData.Controls.Add(this.dgvResults);
this.gbData.Dock = System.Windows.Forms.DockStyle.Fill;
this.gbData.Location = new System.Drawing.Point(10, 150);
this.gbData.Margin = new System.Windows.Forms.Padding(10);
this.gbData.Name = "gbData";
this.gbData.Size = new System.Drawing.Size(1158, 221);
this.gbData.TabIndex = 2;
this.gbData.TabStop = false;
this.gbData.Text = "实验数据";
//
// dgvResults
//
this.dgvResults.AllowUserToAddRows = false;
this.dgvResults.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgvResults.BackgroundColor = System.Drawing.SystemColors.Window;
this.dgvResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dgvResults.ColumnHeadersHeight = 34;
this.dgvResults.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewTextBoxColumn1,
this.dataGridViewTextBoxColumn2,
this.dataGridViewTextBoxColumn3,
this.dataGridViewTextBoxColumn4,
this.dataGridViewTextBoxColumn5,
this.dataGridViewTextBoxColumn6});
this.dgvResults.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgvResults.Location = new System.Drawing.Point(3, 29);
this.dgvResults.Name = "dgvResults";
this.dgvResults.ReadOnly = true;
this.dgvResults.RowHeadersVisible = false;
this.dgvResults.RowHeadersWidth = 62;
this.dgvResults.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.dgvResults.Size = new System.Drawing.Size(1152, 189);
this.dgvResults.TabIndex = 0;
//
// gbChart
//
this.gbChart.Controls.Add(this.formsPlot);
this.gbChart.Dock = System.Windows.Forms.DockStyle.Fill;
this.gbChart.Location = new System.Drawing.Point(10, 391);
this.gbChart.Margin = new System.Windows.Forms.Padding(10);
this.gbChart.Name = "gbChart";
this.gbChart.Size = new System.Drawing.Size(1158, 343);
this.gbChart.TabIndex = 3;
this.gbChart.TabStop = false;
this.gbChart.Text = "加速度变化曲线";
//
// formsPlot
//
this.formsPlot.Dock = System.Windows.Forms.DockStyle.Fill;
this.formsPlot.Location = new System.Drawing.Point(3, 29);
this.formsPlot.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4);
this.formsPlot.Name = "formsPlot";
this.formsPlot.Size = new System.Drawing.Size(1152, 311);
this.formsPlot.TabIndex = 0;
//
// dataGridViewTextBoxColumn1
//
this.dataGridViewTextBoxColumn1.HeaderText = "时间";
this.dataGridViewTextBoxColumn1.MinimumWidth = 8;
this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
this.dataGridViewTextBoxColumn1.ReadOnly = true;
//
// dataGridViewTextBoxColumn2
//
this.dataGridViewTextBoxColumn2.HeaderText = "T1(s)";
this.dataGridViewTextBoxColumn2.MinimumWidth = 8;
this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
this.dataGridViewTextBoxColumn2.ReadOnly = true;
//
// dataGridViewTextBoxColumn3
//
this.dataGridViewTextBoxColumn3.HeaderText = "T2(s)";
this.dataGridViewTextBoxColumn3.MinimumWidth = 8;
this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
this.dataGridViewTextBoxColumn3.ReadOnly = true;
//
// dataGridViewTextBoxColumn4
//
this.dataGridViewTextBoxColumn4.HeaderText = "V1(m/s)";
this.dataGridViewTextBoxColumn4.MinimumWidth = 8;
this.dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4";
this.dataGridViewTextBoxColumn4.ReadOnly = true;
//
// dataGridViewTextBoxColumn5
//
this.dataGridViewTextBoxColumn5.HeaderText = "V2(m/s)";
this.dataGridViewTextBoxColumn5.MinimumWidth = 8;
this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5";
this.dataGridViewTextBoxColumn5.ReadOnly = true;
//
// dataGridViewTextBoxColumn6
//
this.dataGridViewTextBoxColumn6.HeaderText = "加速度(m/s²)";
this.dataGridViewTextBoxColumn6.MinimumWidth = 8;
this.dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6";
this.dataGridViewTextBoxColumn6.ReadOnly = true;
//
// MainForm
//
this.ClientSize = new System.Drawing.Size(1178, 744);
this.Controls.Add(this.mainLayout);
this.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "气垫导轨实验数据监控";
this.mainLayout.ResumeLayout(false);
this.gbSerial.ResumeLayout(false);
this.serialLayout.ResumeLayout(false);
this.buttonPanel.ResumeLayout(false);
this.gbData.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.dgvResults)).EndInit();
this.gbChart.ResumeLayout(false);
this.ResumeLayout(false);
}
// 初始化图表
private void InitializePlot()
{
var plt = formsPlot.Plot;
// 设置图表样式
plt.Title("加速度变化曲线", size: 16);
plt.XLabel("实验序号");
plt.YLabel("加速度 (m/s²)");
plt.Grid(enable: true, color: Color.LightGray);
plt.Style(ScottPlot.Style.Blue1);
// 添加数据序列
plt.AddSignal(new double[] { 0 }, 1, Color.Blue, label: "加速度");
// 添加图例
plt.Legend(location: Alignment.LowerRight);
plt.SetAxisLimits(0, 10, 0, 10);
}
// 加载可用串口
private void LoadAvailablePorts()
{
cmbPorts.Items.Clear();
string[] ports = SerialPort.GetPortNames();
cmbPorts.Items.AddRange(ports);
if (ports.Length > 0) cmbPorts.SelectedIndex = 0;
// 设置波特率选项
cmbBaudRate.Items.AddRange(new object[] { 9600, 19200, 38400, 57600, 115200 });
cmbBaudRate.SelectedIndex = 4; // 默认115200
}
// 连接/断开串口
private void btnConnect_Click(object sender, EventArgs e)
{
if (serialPort == null || !serialPort.IsOpen)
{
try
{
serialPort = new SerialPort(cmbPorts.Text, (int)cmbBaudRate.SelectedItem);
serialPort.DataReceived += SerialPort_DataReceived;
serialPort.Open();
btnConnect.Text = "断开连接";
btnConnect.BackColor = Color.LightCoral;
}
catch (Exception ex)
{
MessageBox.Show($"串口连接错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
serialPort.Close();
serialPort = null;
btnConnect.Text = "连接串口";
btnConnect.BackColor = Color.LightGreen;
}
}
// 串口数据接收处理
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string data = serialPort.ReadLine();
this.Invoke(new Action(() => ProcessData(data)));
}
catch (Exception ex)
{
Console.WriteLine($"数据接收错误: {ex.Message}");
}
}
// 数据处理和显示
private void ProcessData(string rawData)
{
/* 数据格式示例:
* "T1:0.025,T2:0.023,V1:0.4,V2:0.44,A:0.2"
*/
try
{
string[] pairs = rawData.Split(',');
double t1 = 0, t2 = 0, v1 = 0, v2 = 0, acc = 0;
foreach (string pair in pairs)
{
string[] keyValue = pair.Split(':');
if (keyValue.Length != 2) continue;
switch (keyValue[0])
{
case "T1": t1 = double.Parse(keyValue[1]); break;
case "T2": t2 = double.Parse(keyValue[1]); break;
case "V1": v1 = double.Parse(keyValue[1]); break;
case "V2": v2 = double.Parse(keyValue[1]); break;
case "A": acc = double.Parse(keyValue[1]); break;
}
}
// 添加新行到DataGridView
int rowIndex = dgvResults.Rows.Add();
dgvResults.Rows[rowIndex].Cells["Time"].Value = DateTime.Now.ToString("HH:mm:ss.fff");
dgvResults.Rows[rowIndex].Cells["T1"].Value = t1;
dgvResults.Rows[rowIndex].Cells["T2"].Value = t2;
dgvResults.Rows[rowIndex].Cells["V1"].Value = v1;
dgvResults.Rows[rowIndex].Cells["V2"].Value = v2;
dgvResults.Rows[rowIndex].Cells["Acc"].Value = acc;
// 自动滚动到最后一行
dgvResults.FirstDisplayedScrollingRowIndex = dgvResults.RowCount - 1;
// 更新图表
UpdatePlot(acc);
}
catch (Exception ex)
{
Console.WriteLine($"数据处理错误: {ex.Message}");
}
}
// 更新图表数据
private void UpdatePlot(double acc)
{
var plt = formsPlot.Plot;
// 添加新数据点
accelerationData.Add(acc);
dataPointCount++;
// 限制显示点数
if (accelerationData.Count > 100)
{
accelerationData.RemoveAt(0);
}
// 清除原有图表数据
plt.Clear();
// 添加新数据
plt.AddSignal(accelerationData.ToArray(), 1, label: "加速度", color: Color.Blue);
// 设置X轴范围
plt.SetAxisLimitsX(0, accelerationData.Count);
// 自动调整Y轴范围
double min = double.MaxValue;
double max = double.MinValue;
foreach (double val in accelerationData)
{
if (val < min) min = val;
if (val > max) max = val;
}
// 添加一些边距
double range = max - min;
if (range < 0.1) range = 0.1; // 避免过小范围
min = Math.Max(0, min - range * 0.1);
max += range * 0.1;
plt.SetAxisLimitsY(min, max);
// 刷新图表
formsPlot.Render();
}
// 导出数据到CSV
private void btnExport_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "CSV文件|*.csv";
sfd.Title = "保存实验数据";
if (sfd.ShowDialog() == DialogResult.OK)
{
try
{
using (StreamWriter sw = new StreamWriter(sfd.FileName))
{
// 写入列标题
sw.WriteLine("时间,T1(s),T2(s),V1(m/s),V2(m/s),加速度(m/s²)");
// 写入数据
foreach (DataGridViewRow row in dgvResults.Rows)
{
if (!row.IsNewRow)
{
sw.WriteLine(
$"{row.Cells["Time"].Value}," +
$"{row.Cells["T1"].Value}," +
$"{row.Cells["T2"].Value}," +
$"{row.Cells["V1"].Value}," +
$"{row.Cells["V2"].Value}," +
$"{row.Cells["Acc"].Value}");
}
}
}
MessageBox.Show("数据导出成功!", "导出完成",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"导出失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
// 清除数据
private void btnClear_Click(object sender, EventArgs e)
{
if (MessageBox.Show("确定要清除所有数据吗?", "确认清除",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
dgvResults.Rows.Clear();
accelerationData.Clear();
dataPointCount = 0;
// 清除图表数据
var plt = formsPlot.Plot;
plt.Clear();
plt.AddSignal(new double[] { 0 }, 1, label: "加速度", color: Color.Blue);
plt.SetAxisLimits(0, 10, 0, 10);
formsPlot.Render();
}
}
// 程序入口点
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
请你根据这个代码优化一下实验数据导出,要求:导出文件可见且为excel表格