开发者

使用C#和WinForms创建动态图表的两种方法

目录
  • 前言
  • 方法一:在项目启动时实例化图表
    • 全部代码
    • 运行结果
  • 方法二:拖动控件的方法创建图表
    • 工具箱的位置
    • 步骤一
    • 步骤二
    • 步骤三
    • 全部代码
    • 运行结果
  • 扩展
    • 注意事项

      前言

      这次我们将学习如何使用 C# 和 WinForms 创建动态图表。我们编程客栈将使用 Chart 控件来创建图表,并使用多线程技术实现动态更新图表数据的效果。

      方法一:在项目启动时实例化图表

      在 DoWork 方法中,我们使用 Random 类生成随机数作为 Y 值,并使用 Series 对象的 Points 集合来添加数据点。如果数据点数量超过 20 条,我们将移除最旧的数据点,并更新所有数据点的 X 坐标值,以确保仅显示最新的 20 条数据。

      1. 初始化图表

      在窗体的构造函数中,创建一个 Chart 控件,并将其 Dock 属性设置为 Fill,以使其占据整个窗体的空间。然后创建一个 ChartArea,并将其添加到 Chart 控件上。接着创建两个 Series(系列),并将它们都添加到 Chart 控件上。最后将 Chart 控件的 BorderSkin.SkinStyle 属性设置为 None,以隐藏外部边框。

        // 初始化图表
                  chart1 = new Chart
                  {
                      Parent = this,
                      Dock = DockStyle.Fill
                  };
      
                  // 创建一个新的图表区域
                  ChartArea chartArea1 = new ChartArea();
                  chart1.ChartAreas.Add(chartArea1);
      
                  // 设置图表区域的边框颜色为透明
                  chartArea1.BorderColor = Color.FromArgb(255, 0, 0);
      
                  // 创建俩个折线图系列
                  series1 = new Series
                  {
                      ChartType = SeriesChartType.Line
                  };
                  series2 = new Series
                  {
                      ChartType = SeriesChartType.Line
                  };
      
                  // 将系列添加到图表上
                  chart1.Series.Add(series1);
                  chart1.Series.Add(series2);
      
                  // 隐藏图表的外部边框
                  chart1.BorderSkin.SkinStyle = BorderSkinStyle.None;
      
      1. 点击按钮后增加数据点

      当用户点击“开始”按钮时,会触发 Button1_Click 事件处理程序。在该事件处理程序中,创建一个新线程并调用 DoWork 方法,在该方法中不断地添加新数据点。每次添加新数据点时,先生成一个随机数作为 Y 坐标值,然后调用 BeginInvoke 方法,将更新 UI 元素的代码封装在一个 Action 委托中,并将该委托传递给 BeginInvoke 方法。这样可以确保 UI 元素的更新操作是异步执行的,从而避免阻塞 UI 界面。

              private void Button1_Click(object sender, EventArgs e)
              {
                  // 创建新线程
                  Thread thread = new Thread(new ThreadStart(DoWork));
                  thread.Start();
              }
      
      1. 更新数据点的 X 坐标值

      如果数据点的数量超过了20个,就需要移除最旧的数据点。移除操作后,需要更新剩余数据点的 X 坐标值,确保仅显示最新的20个数据点。这是通过循环遍历所有数据点并更新其 X 坐标值实现的。

      1. 刷新图表

      每次添加新数据点后,需要调用 chart1.DataBind() 方法刷新图表,并将 xValue 的值自增1,以便下一次添加新数据点时能够使用正确的 X 坐标值。

       private void DoWork()
              {
                  while (true)
                  {
                      // 检查窗体是否已经关闭
                      if (IsDisposed || Disposing)
                      {
                          return;
                      }
                      // 每次点击按钮时,增加X值和随机Y值
                      Random random = new Random();
                      int yValue1 = random.Next(50, 140);
                      int yValue2 = random.Next(50, 140);
                      // 异步更新 UI 元素
                      BeginInvoke(new Action(() =>
                      {
                          // 更新 UI 元素的代码
                          series1.Points.AddXY(xValue, yValue1);
                          series2.Points.AddXY(xValue, yValue2);
      
                          if (series1.Points.Count > 20)
                          {
                              // 如果数据点数量超过100条,移除最旧的数据点
                              series1.Points.RemoveAt(0);
      
                              // 更新所有数据点的X坐标值,确保仅显示最新的100条数据
                              for (int i = 0; i < series1.Points.Count; i++)
                              {
                                  series1.Points[i].XValue = i + 1;
                              }
                          www.devze.com}
                          if (series2.Points.Count > 20)
                          {
                              // 如果数据点数量超过100条,移除最旧的数据点
                              series2.Points.RemoveAt(0);
      
                              // 更新所有数据点的X坐标值,确保仅显示最新的100条数据
                              for (int i = 0; i < series2.Points.Count; i++)
                              {
                                  series2.Points[i].XValue = i + 1;
                              }
                          }
                          // 更新X值
                          xValue++;
      
                          // 刷新图表
                          chart1.DataBind();
                      }));
      
                      Thread.Sleep(500);
                  }
              }
      

      全部代码

      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Text;
      using System.Threading;
      using System.Threading.Tasks;
      using System.Windows.Forms;
      using System.Windows.Forms.DataVisualization.Charting;
      
      namespace WindowsFormsApp1
      {
          public partial class Form1 : Form
          {
              private readonly Chart chart1;
              private readonly Series series1;
              private readonly Series series2;
              private int xValue = 1; // 初始X值
      
              public Form1()
              {
                  InitializeComponent();
      
                  // 初始化图表
                  chart1 = new Chart
                  {
                      Parent = this,
                      Dock = DockStyle.Fill
                  };
      
                  // 创建一个新的图表区域
                  ChartArea chartArea1 = new ChartArea();
                  chart1.ChartAreas.Add(chartArea1);
      
                  // 设置图表区域的边框颜色为透明
                  chartArea1.BorderColor = Color.FromArgb(255, 0, 0);
      
                  // 创建俩个折线图系列
                  series1 = new Series
                  {
                      ChartType = SeriesChartType.Line
                  };
                  series2 = new Series
                  {
                      ChartType = SeriesChartType.Line
                  };
      
                  // 将系列添加到图表上
                  chart1.Series.Add(series1);
                js  chart1.Series.Add(series2);
      
                  // 隐藏图表的外部边框
                  chart1.BorderSkin.SkinStyle = BorderSkinStyle.None;
              }
              //需要在From1窗体添加一个名为Button1的按钮 一个名为Button1的方法
              private void Button1_Click(object sender, EventArgs e)
              {
                  // 创建新线程
                  Thread thread = new Thread(new ThreadStart(DoWork));
                  thread.Start();
              }
      
              private void DoWork()
              {
                  //循环无限添加点 形成折线图
                  while (true)
                  {
                      // 检查窗体是否编程客栈已经关闭
                      if (IsDisposed || Disposing)
                      {
                          return;
                      }
                      // 每次点击按钮时,增加X值和随机Y值
                      Random random = new Random();
                      int yValue1 = random.Next(50, 140);
                      int yValue2 = random.Next(50, 140);
                      // 异步更新 UI 元素
                      BeginInvoke(new Action(() =>
                      {
                          // 更新 UI 元素的代码
                          series1.Points.AddXY(xValue, yValue1);
                          series2.Points.AddXY(xValue, yValue2);
      
                          if (series1.Points.Count > 20)
                          {
                              // 如果数据点数量超过100条,移除最旧的数据点
                              series1.Points.RemoveAt(0);
      
                              // 更新所有数据点的X坐标值,确保仅显示最新的100条数据
                              for (int i = 0; i < series1.Points.Count; i++)
                              {
                                  series1.Points[i].XValue = i + 1;
                              }
                          }
                          if (series2.Points.Count > 20)
                          {
                              // 如果数据点数量超过100条,移除最旧的数据点
                              series2.Points.RemoveAt(0);
      
                              // 更新所有数据点的X坐标值,确保仅显示最新的100条数据
                              for (int i = 0; i < series2.Points.Count; i++)
                              {
                                  series2.Points[i].XValue = i + 1;
                              }
                          }
                          // 更新X值
                          xValue++;
      
                          // 刷新图表
                          chart1.DataBind();
                      }));
      
                      Thread.Sleep(500);
                  }
              }
          }
      }
      
      

      运行结果

      使用C#和WinForms创建动态图表的两种方法

      在 Form1 构造函数中,我们初始化了图表控件,创建了一个新的图表区域和两个折线图系列,并将这些元素添加到图表控件上。

      在运行程序后,当用户点击按钮时,图表控件将开始显示动态的折线图,随着时间的推移,新的数据点将加入图表中,并移除最旧的数据点。

      这是直接在页面打开的时候进行初始化 一个Chart图表 ,和俩条Series折线图Line

      方法二:拖动控件的方法创建图表

      工具箱的位置

      使用C#和WinForms创建动态图表的两种方法

      步骤一

      输入Chart 将 Chart拖动到From1上

      使用C#和WinForms创建动态图表的两种方法

      步骤二

      打开Chart的属性,找到属性Series,打开集合添加成员类型(series就是一个图表),找到左侧的图表属性ChartType,选择Line。这句话等效于如下代码。

      // 创建俩个折线图系列
      series1 = new Series
      {
          ChartType = SeriesChartType.Line
      };
      series2 = new Series
      {
          ChartType = SeriesChartType.Line
      };
      

      使用C#和WinForms创建动态图表的两种方法

      步骤三

      完成上面步骤最后应该是如下图

      使用C#和WinForms创建动态图表的两种方法

      全部代码

      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Text;
      using System.Threading;
      using System.Threading.Tasks;
      using System.Windows.Forms;
      using System.Windows.Forms.DataVisualization.Charting;
      
      namespace WindowsFormsApp1
      {
          public partial class Form1 : Form
          {
             
              private int xValue = 1; // 初始X值
      
              public Form1()
              {
                  InitializeComponent();  
              }
      
              private void button2_Click(object sender, EventArgs e)
              {
                  // 创建新线程
                  Thread thread = new Thread(new ThreadStart(DoWork));
                  thread.Start();
              }
      
              private void DoWork()
              {
                  //将俩条折线取出来
                  Series series1 = chart2.Series[0];
                  Series series2 = chart2.Series[1];
      
                  while (true)
                  {
                      // 检查窗体是否已经关闭
                      if (IsDisposed || Disposing)
                      {
                          return;
                      }
                      // 每次点击按钮时,增加X值和随机Y值
                      Random random = new Random();
                      int yValue1 = random.Next(50, 140);
                      int yValue2 = random.Next(50, 140);
                      // 异步更新 UI 元素
                      BeginInvoke(new Action(() =>
                      {
                          // 更新 UI 元素的代码
                          series1.Points.AddXY(xValue, yValue1);
                          series2.Points.AddXY(xValue, yValue2);
      
                          if (series1.Points.Count > 20)
                          {
                              // 如果数据点数量超过100条,移除最旧的数据点
                              series1.Points.RemoveAt(0);
      
                              // 更新所有数据点的X坐标值,确保仅显示最新的100条数据
                              for (int i = 0; i < series1.Points.Count; i++)
                              {
                                  series1.Points[i].XValue = i + 1;
                              }
                          }
                          if (series2.Points.Count > 20)
                          {
                              // 如果数据点数量超过100条,移除最旧的数据点
                              series2.Points.RemoveAt(0);
      
                              // 更新所有数据点的X坐标值,确保仅显示最新的100条数据
                              for (int i = 0; i < series2.Points.Count; i++)
                              {
                                  series2.Points[i].XValue = i + 1;
                              }
                          }
                          // 更新X值
                          xValue++;
      
                          // 刷新图表
                          chart2.DataBind();
                      }));
      
                      Thread.Sleep(500);
                  }
              }
          }
      }
      
      

      运行结果

      使用C#和WinForms创建动态图表的两种方法

      扩展

      以下是一些常见的 chart2.Series 属性和方法的使用示例:

      //添加一个新系列:
      Series newSeries = new Series();
      chart2.Series.Add(newSeries);
      
      //删除指定索引位置的系列:
      chart2.Series.RemoveAt(index);
      
      //获取指定索引位置的系列:
      Series series = chart2.Series[index];
      
      //遍历所有系列:
      foreach (Series series in chart2.Series)
      {
          // 对每个系列执行操作
      }
      
      //设置系列的属性,如图表类型和系列名称:
      series.ChartType = SeriesChartType.Line;
      series.Name = "Series Name";
      
      //清空所有系列:
      chart2.Series.Clear();
      

      注意事项

      必须用线程来启动这个方法,异步更新 UI 元素,防止动态卡死。

      以上就是使用C#和WinForms创建动态图表的两种方法的详细内容,更多关于C# WinForms创www.devze.com建动态图表的资料请关注编程客栈(www.devze.com)其它相关文章!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜