【问题标题】:ZedGraph custom graphZedGraph 自定义图
【发布时间】:2012-04-16 09:55:16
【问题描述】:

我想用 ZedGraph 制作以下动态图表: 如何使 ZedGraph 轴反转和时间轴?谢谢

UPD 1: 我必须尝试使用​​以下代码:

GraphPane myPane = zg1.GraphPane;
            myPane.YAxis.Type = AxisType.Date;
            myPane.YAxis.Scale.MajorUnit = DateUnit.Minute;
            myPane.YAxis.Scale.MinorUnit = DateUnit.Second;
            myPane.XAxis.IsVisible = false;
            myPane.X2Axis.IsVisible = true;
            myPane.X2Axis.MajorGrid.IsVisible = true;
            myPane.X2Axis.Scale.Min = 0;
            myPane.X2Axis.Scale.Max = 600;
            myPane.YAxis.Scale.Format = "HH:mm:ss";
            PointPairList list = new PointPairList();
            PointPairList list2 = new PointPairList();
            for (int i = 0; i < 36; i++)
            {
                double x = (double)i * 5.0;
                double y = (double)new XDate(DateTime.Now.AddSeconds(i));
                list.Add(y, x);
                //list2.Add(y2, x);
                listBox1.Items.Add("x = " + x + " y = " + y);
            }

            // Generate a red curve with diamond symbols, and "Alpha" in the legend
            LineItem myCurve = myPane.AddCurve("Alpha",
                list, Color.Red, SymbolType.None);
            // Fill the symbols with white
            myCurve.Symbol.Fill = new Fill(Color.White);
                        myPane.Y2Axis.MajorGrid.IsVisible = true;
            // Align the Y2 axis labels so they are flush to the axis
            myPane.Y2Axis.Scale.Align = AlignP.Inside;

            // Fill the axis background with a gradient
            myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
            zg1.IsShowPointValues = true;
            zg1.AxisChange();
            // Make sure the Graph gets redrawn
            zg1.Invalidate();

但我错了:

UPD2

我有多线程代码:

private TimerCallback ReadTimerCallback;
        private LineItem myCurve;
        private Random rnd = new Random(500);
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            GraphPane myPane = zg1.GraphPane;

            myPane.XAxis.IsVisible = false;

            myPane.X2Axis.IsVisible = true;
            myPane.X2Axis.MajorGrid.IsVisible = true;
            myPane.X2Axis.Scale.Min = 0;
            myPane.X2Axis.Scale.Max = 600;

            myPane.YAxis.IsVisible = false;

            myPane.Y2Axis.IsVisible = true;
            myPane.Y2Axis.Scale.MajorUnit = DateUnit.Minute;
            myPane.Y2Axis.Scale.MinorUnit = DateUnit.Second;
            myPane.Y2Axis.Scale.Format = "HH:mm:ss";
            myPane.Y2Axis.Type = AxisType.DateAsOrdinal;

            // As we get more data we want to add it on to the end of the curve
            // and we also want to get the scale so that we can shift it along
            double? oringinalLastDate;
            XDate firstDate;
            if (myPane.CurveList.Count == 0)
            {
                myCurve = myPane.AddCurve("Alpha",
                                          new PointPairList(),
                                          Color.Red,
                                          SymbolType.None);
                firstDate = new XDate(DateTime.Now);
                oringinalLastDate = null;
            }
            else
            {
                myCurve = (LineItem)myPane.CurveList[0];
                firstDate = myCurve.Points[myCurve.Points.Count - 1].Y;
                oringinalLastDate = myPane.Y2Axis.Scale.Max;
            }

            /*for (int i = 0; i < 36; i++)
            {
                double x = i * 5.0;
                firstDate.AddSeconds(i);

                myCurve.AddPoint(x, firstDate);

                //listBox1.Items.Add("x = " + x + " y = " + firstDate);
            }*/

            myCurve.Symbol.Fill = new Fill(Color.White);
            myCurve.IsX2Axis = true;
            myCurve.IsY2Axis = true;
            //myPane.Y2Axis.Scale.IsReverse = true;

            myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
            zg1.IsShowPointValues = true;

            // Now make the minimum of the scale, the maximum that it was so
            // the graph shifts
            if (oringinalLastDate.HasValue)
                myPane.Y2Axis.Scale.Min = oringinalLastDate.Value;

            zg1.AxisChange();
            zg1.Invalidate();
            AutoResetEvent ReadautoEvent = new AutoResetEvent(false);
            ReadTimerCallback = new TimerCallback(this.ShowData);
            System.Threading.Timer timer = new System.Threading.Timer(ReadTimerCallback, ReadautoEvent, 100, 1000);

        }

        private void ShowData (object Object )
        {
            this.myCurve.AddPoint(rnd.Next(500, 600), new XDate(DateTime.Now));
        }

UPD3: 我想向下移动 Y 轴,而不是缩放这个轴。我只更新了 1 分钟的图表:

【问题讨论】:

    标签: c# charts customization zedgraph


    【解决方案1】:

    我认为您希望 DateAsOrdinal(而不是 Date)为您提供更好的日期表示(尽管如果您对此感到满意,可能不会)并且您需要将曲线上的 IsX2Axis 和 IsY2Axis 属性设置为 true。

    这是您的代码的更新版本,它显示了我的意思 - 这是您需要的吗? (在给定数据值的情况下,它不会像您绘制的那样是波浪线,并且 x 轴刻度从 0 而不是 100 开始,因为您的代码已将其明确设置为 0,所以我假设这就是您想要)。

    每次调用它时总是会附加更多数据(我假设您是从按钮 1 调用它)并且它会移动轴的最小值,因此您只显示最新的数据位 - 如果您没有设置 Min 值,您将看到一条摆动的线,因为它显示了所有数据。

    GraphPane myPane = zg1.GraphPane;            
    
    myPane.XAxis.IsVisible = false;
    
    myPane.X2Axis.IsVisible = true;
    myPane.X2Axis.MajorGrid.IsVisible = true;
    myPane.X2Axis.Scale.Min = 0;
    myPane.X2Axis.Scale.Max = 600;
    
    myPane.YAxis.IsVisible = false;
    
    myPane.Y2Axis.IsVisible = true;
    myPane.Y2Axis.Scale.MajorUnit = DateUnit.Minute;
    myPane.Y2Axis.Scale.MinorUnit = DateUnit.Second;
    myPane.Y2Axis.Scale.Format = "HH:mm:ss";
    myPane.Y2Axis.Type = AxisType.DateAsOrdinal;
    
    // As we get more data we want to add it on to the end of the curve
    // and we also want to get the scale so that we can shift it along
    double? oringinalLastDate;
    XDate firstDate;
    LineItem myCurve;
    if(myPane.CurveList.Count == 0)
    {
        myCurve = myPane.AddCurve("Alpha",
                                  new PointPairList(),
                                  Color.Red,
                                  SymbolType.None);
        firstDate = new XDate(DateTime.Now);
        oringinalLastDate = null;
    }
    else
    {
        myCurve = (LineItem)myPane.CurveList[0];
        firstDate = myCurve.Points[myCurve.Points.Count - 1].Y;
        oringinalLastDate = myPane.Y2Axis.Scale.Max;
    }            
    
    for (int i = 0; i < 36; i++)
    {
        double x = i * 5.0;
        firstDate.AddSeconds(i);
    
        myCurve.AddPoint(x, firstDate);
    
        listBox1.Items.Add("x = " + x + " y = " + firstDate);
    }
    
    myCurve.Symbol.Fill = new Fill(Color.White);
    myCurve.IsX2Axis = true;
    myCurve.IsY2Axis = true;
    
    myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
    zg1.IsShowPointValues = true;
    
    // Now make the minimum of the scale, the maximum that it was so
    // the graph shifts
    if (oringinalLastDate.HasValue)
        myPane.Y2Axis.Scale.Min = oringinalLastDate.Value;
    
    zg1.AxisChange();            
    zg1.Invalidate();
    

    更新

    如果您想使用 500 到 600 之间的随机数每秒更新一次图表,应该这样做(每添加 3 个点后,y 轴上的刻度会移动):

    private int pointCount;
    private double? scaleMin = null;
    private static readonly Random rnd = new Random();
    
    private void button1_Click(object sender, EventArgs e)
    {
        GraphPane myPane = zg1.GraphPane;
    
        myPane.XAxis.IsVisible = false;
    
        myPane.X2Axis.IsVisible = true;
        myPane.X2Axis.MajorGrid.IsVisible = true;
        myPane.X2Axis.Scale.Min = 0;
        myPane.X2Axis.Scale.Max = 600;
    
        myPane.YAxis.IsVisible = false;
    
        myPane.Y2Axis.IsVisible = true;
        myPane.Y2Axis.Scale.MajorUnit = DateUnit.Minute;
        myPane.Y2Axis.Scale.MinorUnit = DateUnit.Second;
        myPane.Y2Axis.Scale.Format = "HH:mm:ss";
        myPane.Y2Axis.Type = AxisType.DateAsOrdinal;
    
        LineItem myCurve = myPane.AddCurve("Alpha",
                                      new PointPairList(),
                                      Color.Red,
                                      SymbolType.None);
    
        myCurve.Symbol.Fill = new Fill(Color.White);
        myCurve.IsX2Axis = true;
        myCurve.IsY2Axis = true;
    
        myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
        zg1.IsShowPointValues = true;
    
        pointCount = 0;
    
        var t = new System.Windows.Forms.Timer();
        t.Interval = 1000;
        t.Tick += ShowData;
    
        Thread.Sleep(100);
    
        t.Start();
    }
    
    private void ShowData(object sender, EventArgs e)
    {
        var t = (System.Windows.Forms.Timer) sender;
        t.Enabled = false;
    
        pointCount++;
    
        int x = rnd.Next(500, 600);
        var y = new XDate(DateTime.Now);
    
        GraphPane myPane = zg1.GraphPane;
    
        if (scaleMin == null) scaleMin = myPane.Y2Axis.Scale.Max;
    
        LineItem myCurve = (LineItem)myPane.CurveList[0];            
    
        myCurve.AddPoint(x, y);
    
        // After 3 points are added move the scale along
        if (pointCount > 3)
        {
            myPane.Y2Axis.Scale.Min = scaleMin.Value;
            scaleMin = myPane.Y2Axis.Scale.Max;
        }
    
        zg1.AxisChange();
        zg1.Invalidate();
    
        t.Enabled = true;
    }
    

    【讨论】:

    • 谢谢kmp!这是我需要的,但我想让时间轴运动,以可视化实时数据。这个怎么做?
    • 我已经更新了答案——希望我已经理解你了——现在每次调用代码时都会添加数据,并调整最小轴点,这样你就会看到最后 35 秒的数据。
    • 1.我必须使用 myCurve.AddPoint(x, firstDate) 添加新数据并通过 myPane.Y2Axis.Scale.Min = oringinalLastDate.Value 设置最小比例? 2. 我可以从另一个线程添加点到 myCurve 吗?
    • 1.是的,这就是我所做的,因为我想向您展示保留图表绘制的所有数据并仅移动轴。这样,如果您愿意,您可以不设置 Min 值,您将在添加时看到所有数据。或者,您可以只使用原始机制,每次都从一个空的点列表开始。 2. 是的,你可以这样做——我给出的示例中的所有代码都可以在不同的线程中运行,除了将项目添加到 listBox 的行——你需要在那里调用 Invoke。
    • 我尝试在每 1 秒升高一次的计时器中向 myCurve 添加点,但图表中未显示点。我做错了什么?我已经更新了问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    相关资源
    最近更新 更多