2012-04-16 15 views
6

Chcę wykonać wtih ZedGraph śledząc dynamicznie wykres: enter image description here Jak dokonać odwrócenia osi ZedGraph i osi czasu? DziękiNiestandardowy wykres ZedGraph

UPD 1: Muszę spróbować z następującego kodu:

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

Ale biorę coś złego: enter image description here

UPD2:

mam kod wielowątkowość:

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: Chcę przesunąć w dół Oś Y, a nie przeskalować tej osi. I I zostały zaktualizowane wykres tylko 1 minuty: enter image description here

Odpowiedz

3

myślę chcesz DateAsOrdinal (zamiast Date), w celu uzyskania lepszych date reprezentacje (chociaż może nie, jeśli jesteś z niego zadowolony) i trzeba ustawić IsX2Axis oraz właściwości IsY2Axis na krzywej do wartości true.

Oto zaktualizowana wersja Twojego kodu, która pokazuje, co mam na myśli - czy tego potrzebujesz? (nie będzie to linia falista, jaką narysowałeś, biorąc pod uwagę wartości danych, a skala osi X zaczyna się od 0, a nie 100, jak w twoim rysunku, ale to dlatego, że twój kod miał wyraźnie ustawiony na 0, więc zakładam, że to ty chcieć).

Zawsze będzie dodawać więcej danych za każdym razem, gdy zostanie wywołany (zakładam, że wywołujesz go z przycisku1) i przesunie minimalną wartość osi, dzięki czemu wyświetlasz tylko najnowszy bit danych - jeśli nie ustawisz wartości Min, zobaczysz chwiejną linię, która pokazuje wszystkie dane.

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

Aktualizacja

Jeśli chcesz zaktualizować wykres raz drugi z losową liczbę między 500 a 600 to powinno wystarczyć (po raz 3 punkty są dodawane, skala na osi Y przesuwa się wzdłuż):

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; 
} 
+0

Dzięki kmp! Tego właśnie potrzebuję, ale chcę uczynić oś czasu w ruchu, aby wizualizować dane w czasie rzeczywistym. Jak to zrobić? – amaranth

+0

Zaktualizowałem odpowiedź - mam nadzieję, że Cię zrozumiałem - dane są dodawane za każdym razem, gdy kod jest teraz wywoływany, a minimalny punkt osi jest dostosowywany, dzięki czemu zobaczysz ostatnie 35 sekund danych. – kmp

+0

1. Muszę dodać nowe dane z myCurve.AddPoint (x, firstDate) i ustawić minimalną skalę przez myPane.Y2Axis.Scale.Min = oringinalLastDate.Value? 2. Czy mogę dodawać punkty do myCurve z innego wątku? – amaranth

Powiązane problemy