图表:红色X尝试在索引图表中显示多个系列时出错

时间:2016-08-08 01:26:25

标签: c# windows winforms charts

我有一个C#图表问题。

这是使用System.Windows.Forms.DataVisualization.Charting

我的系列配置为索引:

   {
          Name = name,
          Color = color,
          IsVisibleInLegend = false,
          IsXValueIndexed = true,
          ChartType = 
                  System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine
   };

我在此图表中有3个系列

我通过事件处理程序

向系列添加数据
for (int i = 0; i < samples; i++)
{
    double time_point = DData[i * 4]       
    chart1.Series[0].Points[lastSample + i].XValue = time_point;
    chart1.Series[0].Points[lastSample + i].YValues[0] = DData[i * 4 + 1];
    chart1.Series[1].Points[lastSample + i].XValue = time_point;
    chart1.Series[1].Points[lastSample + i].YValues[0] = DData[i * 4 + 2];
    chart1.Series[2].Points[lastSample + i].XValue = time_point;
    chart1.Series[2].Points[lastSample + i].YValues[0] = DData[i * 4 + 3];
}
lastSample = (lastSample + samples) % maxPlotPoints;
chart1.Invalidate();

问题如下:

  • 如果我单独打开每个系列(通过chart1.Series [0] .Enabled),它们都可以正常工作
  • 如果我一次打开超过1个系列,则会出现一个大的红色X而不是图表,我必须重新启动应用程序以恢复流式图表。这可以立即发生,也可以在几秒钟后发生。
  • 如果我将time_point设置为其他数字,例如0,则此问题不会发生,并且所有3个图表都可以同时显示

接下来,我理解当每个系列对于相同的Point []位置具有不同的X值时会发生这种情况。但我明确地将所有3个系列设置为使用相同的time_point

我的下一个假设是事件处理程序在前一个线程完成之前执行了脚步。

所以我在图表调用周围添加了一个锁,它没有帮助

private Object thisLock = new Object();
lock (thisLock)
{

}

我的问题是:

  1. 有没有人知道是否还有其他原因造成这种情况?

  2. 是否可以仅使用图表第一个系列的X索引,但同时显示所有3个系列?

1 个答案:

答案 0 :(得分:0)

编辑:这个修复不起作用,问题消失了,一段时间后又回来了

TaW上面的评论帮助我解决了这个问题。

这似乎是微软图表的问题

我最初虽然它是由于EventHandler在它完成之前多次触发,但我选择使用一个Queh,它将填充一个EventHandler并在一个单独的线程上出列。

问题仍然存在。

问题的解决方案是简单地将IsXValueIndexed设置为 false 然后在绘制图表之前将其设置为 true

以下是使用的代码

如果有人想知道这是做什么的: 它随着时间的增加在图表上同时绘制3个值。 图表从左到右更新而不是滚动(想想医院中的EKG机器) 有一个固定的总点数设置为 maxPlotPoints EventHandler接收一些包含一定数量点= samplePoints 的数据包(此处构成)。 它构造一个 DataPoints 结构并将其添加到队列

一个单独的线程 MainTask 将一个元素从DataPoints中取出,并使用它来填充三个系列中每个元素的100个点。然后该部分增加到下一个100点,依此类推。

如果您想连续绘制固定数量的点数

,这非常有用

不幸的是,我似乎无法将TaW上面的答案标记为正确,因为它在评论中。但如果您能解释如何做到这一点,我会很乐意尝试。感谢

    private struct DataPoint
    {
        public double timePoint;
        public double X;
        public double Y;
        public double Z;
    }
    private struct DataPoints
    {
        public DataPoints(int samples)
        {
            dataPoints = new DataPoint[samples];
        }
        public DataPoint[] dataPoints;
    }

    Queue queue = new Queue();
    int lastSample = 0;
    static int maxPlotPoints = 1000;
    static int samplePoints = 100;

    public ChartForm(UdpMgrControl RefUdpMgr, byte GyroChartNum, string ConfigFile)
    {
        for ( Row = 0; Row < 3; Row++)
        {   
            var series1 = new System.Windows.Forms.DataVisualization.Charting.Series
            {
               Name = name,
               Color = Color.Blue,
               IsVisibleInLegend = false,
               IsXValueIndexed = true,
               ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine
            };

            //Fill in chart with blank points
            for (int i = 0; i < maxPlotPoints; i++)
            {
                series1.Points.AddY(0);
            }

            chart1.Series.Add(series1);
        }

        chart1.Series[0].Enabled = true;
        chart1.Series[1].Enabled = true;
        chart1.Series[2].Enabled = true;

        running = true;
        Thread main_thread = new Thread(new ThreadStart(this.MainTask));

    }

    private void OutputHandler(byte[] DData)
    {
        if (running)
        {
            DataPoints data_element = new DataPoints(samplePoints);
            for (int i = 0; i < samplePoints; i++)
            {
                data_element.dataPoints[i].X = DData[i].X;
                data_element.dataPoints[i].Y = DData[i].Y;
                data_element.dataPoints[i].Z = DData[i].Z;
                data_element.dataPoints[i].timePoint = DData[i].timePoint;
            }
            queue.Enqueue(data_element);
        }
    }
    private void MainTask()
    {
        while (running)
        {
            try
            {
                if (queue.Count > 0)
                {
                    chart1.Series[0].IsXValueIndexed = false;
                    chart1.Series[1].IsXValueIndexed = false;
                    chart1.Series[2].IsXValueIndexed = false;

                    DataPoints data_element = (DataPoints)queue.Dequeue();
                    for (int i = 0; i < data_element.dataPoints.Length; i++)
                        {
                            chart1.Series[0].Points[lastSample + i].XValue = data_element.dataPoints[i].timePoint;
                            chart1.Series[0].Points[lastSample + i].YValues[0] = data_element.dataPoints[i].X;

                            chart1.Series[1].Points[lastSample + i].XValue = data_element.dataPoints[i].timePoint;
                            chart1.Series[1].Points[lastSample + i].YValues[0] = data_element.dataPoints[i].Y;

                            chart1.Series[2].Points[lastSample + i].XValue = data_element.dataPoints[i].timePoint;
                            chart1.Series[2].Points[lastSample + i].YValues[0] = data_element.dataPoints[i].Z;
                        }

                    //Adjust the next location to end of first
                    lastSample = (lastSample + samples) % maxPlotPoints;

                    chart1.Series[0].IsXValueIndexed = true;
                    chart1.Series[1].IsXValueIndexed = true;
                    chart1.Series[2].IsXValueIndexed = true;

                    GC_UpdateDataGrids();
                    chart1.Invalidate();
                }
                else
                {
                    Thread.Sleep(10);
                }
            }
            catch (Exception error)
            {
                LogErrors.AddErrorMsg(error.ToString());
            }
        }
    }