当前位置: 代码网 > it编程>编程语言>Asp.net > 使用C#和WinForms创建动态图表的两种方法

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

2025年09月26日 Asp.net 我要评论
前言这次我们将学习如何使用 c# 和 winforms 创建动态图表。我们将使用 chart 控件来创建图表,并使用多线程技术实现动态更新图表数据的效果。方法一:在项目启动时实例化图表在 dowork

前言

这次我们将学习如何使用 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;
                        }
                    }
                    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);
            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);
            }
        }
    }
}

运行结果

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

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

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

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

工具箱的位置

步骤一

输入chart 将 chart拖动到from1上

步骤二

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

// 创建俩个折线图系列
series1 = new series
{
    charttype = seriescharttype.line
};
series2 = new series
{
    charttype = seriescharttype.line
};

步骤三

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

全部代码

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

运行结果

扩展

以下是一些常见的 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创建动态图表的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com