Winform Chart控件 增加跟随鼠标移动的交叉线并显示该x轴上的全部数据

菜鸡一个,不喜勿喷~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~纯属记录

有大佬提供更好的解决思路不胜感激。

最近在使用MSChart控件做数据显示项目,领导要求要像股票软件,跟随鼠标移动显示数据。

查阅大量CSDN文档加自己调试[狗头][狗头][狗头]

PS:还要求动画 还未实现

思路:

1、根据鼠标位置获取对应在chart控件X轴位置 --使用MouseMover事件

2、在点击位置,画个label 当交叉线 label的高度和y轴坐标需要转换

3、遍历判断该位置在哪两个数据点中间,将label"磁吸"过去,取左边点(待优化)

4、显示tooltip

(别喷我啊,喷我就哭给你看) 

private int _CurrentXValue = 0;//记录当前鼠标x轴位置


private void chtDemand_MouseMove(object sender, MouseEventArgs e)
        {
            HitTestResult myTestResult = chtDemand.HitTest(e.X, e.Y);
            if (myTestResult.ChartElementType == ChartElementType.DataPoint || myTestResult.ChartElementType == ChartElementType.PlottingArea ||
                myTestResult.ChartElementType == ChartElementType.Gridlines)
            {
                if(_CurrentXValue == e.X)//鼠标没移动就不刷了
                {
                    return;
                }
                _CurrentXValue = e.X;
                ChartArea chartArea = chtDemand.ChartAreas[0];

                lblLineH.Visible = true;

                int dstart = (int)chartArea.AxisY.ValueToPixelPosition(chtDemand.ChartAreas[0].AxisY.Maximum);
                int dend = (int)chartArea.AxisY.ValueToPixelPosition(chtDemand.ChartAreas[0].AxisY.Minimum);

                lblLineH.Height = dend - dstart;//高度=Y轴高度
                lblLineH.Width = 1;
                lblLineH.Location = new Point(e.X, dstart);


                //鼠标坐标转换成chart坐标
                double xValue = chartArea.AxisX.PixelPositionToValue(e.X);
                for (int i = 0; i < chtDemand.Series[0].Points.Count - 1; i++)
                {
                    if (chtDemand.Series[0].Points[i].XValue <= xValue && xValue <= chtDemand.Series[0].Points[i + 1].XValue)
                    {
                        DataPoint p1 = chtDemand.Series[0].Points[i];
                        DataPoint p2 = chtDemand.Series[1].Points[i];
                        DataPoint p3 = chtDemand.Series[2].Points[i];
                        DataPoint p4 = chtDemand.Series[3].Points[i];
                        DateTime pointDateTime = DateTime.FromOADate(p1.XValue);

                        string str = string.Format("发生时间:{0}\r\n正向有功总需量(kW):{1}\r\nA相正向有功总需量(kW):{2}\r\nB相正向有功总需量(kW):{3}\r\nC相正向有功总需量(kW):{4}"
                          , pointDateTime.ToString("HH:mm:ss"), p1.YValues[0], p2.YValues[0], p3.YValues[0], p4.YValues[0]);
                        toolTip1.Active = true;//form里拖个tooltip

                        toolTip1.Show(str, chtDemand, e.X, e.Y);
                    }
                }
            }
            else
            {
                lblLineH.Visible = false;
                toolTip1.Active = false;

            }
        }

心得:静下来心来思考才是解决问题的最佳途径

 

 

~~~~~~~~~~~~~~~~~优化分割线
优化了下

for循环的作用应该就是确定是 为哪个数据点 

磁吸数据点也优化为更靠近哪一边的 

如果为正确数据点 tooltip就显示,如果不是就不显示

 

private void chtDemand_MouseMove(object sender, MouseEventArgs e)
        {
            HitTestResult myTestResult = chtDemand.HitTest(e.X, e.Y);
            if (myTestResult.ChartElementType == ChartElementType.DataPoint || myTestResult.ChartElementType == ChartElementType.PlottingArea ||
                myTestResult.ChartElementType == ChartElementType.Gridlines)
            {
                if(_CurrentXValue == e.X)
                {
                    return;
                }
                _CurrentXValue = e.X;
                ChartArea chartArea = chtDemand.ChartAreas[0];

                if (chtDemand.Series[0].Points.Count < 1)
                {
                    lblLineH.Visible = false;
                }
                else
                {
                    lblLineH.Visible = true;
                }

                int dstart = (int)chartArea.AxisY.ValueToPixelPosition(chtDemand.ChartAreas[0].AxisY.Maximum);
                int dend = (int)chartArea.AxisY.ValueToPixelPosition(chtDemand.ChartAreas[0].AxisY.Minimum);

                lblLineH.Height = dend - dstart;
                lblLineH.Width = 1;
                lblLineH.Location = new Point(e.X, dstart);


                //鼠标坐标转换成chart坐标
                double xValue = chartArea.AxisX.PixelPositionToValue(e.X);
                int index = 9999;
                for (int i = 0; i < chtDemand.Series[1].Points.Count - 1; i++)//已曲线1为主 曲线0被添加了 23:59:59 占位
                {
                    DataPoint last = chtDemand.Series[0].Points[i];
                    DataPoint next = chtDemand.Series[0].Points[i + 1];

                    //DateTime lastPointDateTime = DateTime.FromOADate(last.XValue);
                    //double error = (lastPointDateTime.AddMinutes(1)).ToOADate() - lastPointDateTime.ToOADate();//误差为1分钟内  
//可以判断是否在某点的左右1分钟范围 修改下面的if就可以

                    if (last.XValue <= xValue && xValue <= next.XValue)//确定在哪两个点中间
                    {
                        double split = (last.XValue + next.XValue) / 2;
                        if (split <= xValue)
                        {
                            index = i + 1;
                        }
                        else
                        {
                            index = i;
                        }                 
                    }

                }
                if(index != 9999)
                {
                    DataPoint p1 = chtDemand.Series[0].Points[index];
                    DataPoint p2 = chtDemand.Series[1].Points[index];
                    DataPoint p3 = chtDemand.Series[2].Points[index];
                    DataPoint p4 = chtDemand.Series[3].Points[index];
                    DateTime pointDateTime = DateTime.FromOADate(p1.XValue);

                    string str = string.Format("发生时间:{0}\r\n总功率因数:{1}\r\nA相功率因数:{2}\r\nB相功率因数:{3}\r\nC相功率因数:{4}"
                      , pointDateTime.ToString("HH:mm:ss"), p1.YValues[0], p2.YValues[0], p3.YValues[0], p4.YValues[0]);
                    toolTip1.Active = true;
                    toolTip1.Show(str, chtDemand, e.X, e.Y);
                }
                else
                {
                    toolTip1.Active = false;
                }

            }
            else
            {
                lblLineH.Visible = false;
                toolTip1.Active = false;

            }
        }

 

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Winform中实现Chart控件鼠标点击显示波形上相应点对应坐标轴的x,y值,可以按照以下步骤进行操作: 1. 在Winform窗体中添加Chart控件。 2. 在窗体的Load事件中添加以下代码,用于绘制波形图: ``` private void Form1_Load(object sender, EventArgs e) { // 添加数据chart1.Series[0].Points.AddXY(1, 2); chart1.Series[0].Points.AddXY(2, 3); chart1.Series[0].Points.AddXY(3, 4); chart1.Series[0].Points.AddXY(4, 5); chart1.Series[0].Points.AddXY(5, 6); // 设置图表区域背景色 chart1.ChartAreas[0].BackColor = Color.White; // 设置X轴和Y轴的标题 chart1.ChartAreas[0].AxisX.Title = "X轴"; chart1.ChartAreas[0].AxisY.Title = "Y轴"; // 设置X轴和Y轴的最小值和最大值 chart1.ChartAreas[0].AxisX.Minimum = 0; chart1.ChartAreas[0].AxisX.Maximum = 6; chart1.ChartAreas[0].AxisY.Minimum = 0; chart1.ChartAreas[0].AxisY.Maximum = 7; // 设置X轴和Y轴的刻度间隔 chart1.ChartAreas[0].AxisX.Interval = 1; chart1.ChartAreas[0].AxisY.Interval = 1; // 设置数据点的标记类型 chart1.Series[0].MarkerStyle = MarkerStyle.Circle; chart1.Series[0].MarkerSize = 10; } ``` 3. 在Chart控件的MouseClick事件中添加以下代码,用于在点击波形上的点时显示相应点对应坐标轴的x,y值: ``` private void chart1_MouseClick(object sender, MouseEventArgs e) { HitTestResult result = chart1.HitTest(e.X, e.Y); if (result.ChartElementType == ChartElementType.DataPoint) { double xValue = result.Series.Points[result.PointIndex].XValue; double yValue = result.Series.Points[result.PointIndex].YValues[0]; MessageBox.Show(string.Format("X: {0}\nY: {1}", xValue, yValue)); } } ``` 以上代码中,HitTest方法用于获取鼠标点击的位置所对应的数据点,然后可以通过PointIndex属性获取数据点的索引,再通过XValue和YValues属性获取相应的x和y值。最后,使用MessageBox控件显示x和y值即可。 注意:在添加Chart控件时,需要添加Series,并设置ChartType属性为Line,才能绘制出波形图。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值