问题
I want to make wtih ZedGraph following dynamically chart:
How to make ZedGraph axes reverse and and time axis? ThanksUPD 1: I have to try with following code:
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();
But I take something wrong:
UPD2:
I have code for multithreading:
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: I want to move down Y axis, not scale this axis. And I have updated chart only 1 minute:
回答1:
I think you want DateAsOrdinal (instead of Date), to give you better date representations (though maybe not if you are happy with it) and you need to set the IsX2Axis and IsY2Axis properties on the curve to true.
Here is an updated version of your code that shows what I mean - is this what you need? (it will not be a wavy line like you have drawn given the data values and the x axis scale starts at 0 not 100 as in your drawing but that is because your code had it explicitly set to 0 so I am assuming that is what you want).
It will always append more data every time it is called (I am assuming you are calling it from your button1) and it will shift the minimum value for the axis along so you are showing just the most recent bit of data - if you do not set the Min value you will see a wobbly line as it is showing all the data.
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();
Update
If you want to update the chart once a second with a random number between 500 and 600 this should do it (after every 3 points are added, the scale on the y axis moves along):
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;
}
来源:https://stackoverflow.com/questions/10172001/zedgraph-custom-graph