如何使用 C# 设置日期时间图表的最小值和最大值?
How to set minimum and maximum values for date time chart using c#?
我试图在我的 windows 应用程序中绘制一个包含每一秒实时数据的折线图。为此,我需要为图表设置最小值(0 秒)和最大值(10 分钟)。 10 分钟后,最小值为 10 分钟,最大值为 20 分钟。所以我每次都必须显示10分钟的数据。我需要从一开始就用滚动条显示以前的数据。我尝试了以下代码,但无法设置 chart.Please 的最小值和最大值解决了我的问题。
series1.XValueType = ChartValueType.DateTime;
series1.IsXValueIndexed = true;
series1.YAxisType = AxisType.Primary;
series1.ChartType = SeriesChartType.Line;
this.chart1.Series.Add(series1);
series2.XValueType = ChartValueType.DateTime;
series2.IsXValueIndexed = true;
series2.YAxisType = AxisType.Secondary;
series2.ChartType = SeriesChartType.Line;
this.chart1.Series.Add(series2);
chart1.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss";
chart1.ChartAreas[0].CursorX.IntervalType = DateTimeIntervalType.Seconds;
chart1.ChartAreas[0].CursorX.AutoScroll = true;
chart1.ChartAreas[0].CursorY.AutoScroll = true;
chart1.ChartAreas[0].AxisX.ScrollBar.Size = 15;
chart1.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All;
chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = false;
chart1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisY2.ScaleView.Zoomable = true;
chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
DateTime minValue, maxValue;
minValue = DateTime.Now;
maxValue = minValue.AddSeconds(600);
chart1.ChartAreas[0].AxisX.Minimum = minValue.ToOADate();
chart1.ChartAreas[0].AxisX.Maximum = maxValue.ToOADate();
chart1.ChartAreas[0].AxisX.ScaleView.Zoom(chart1.ChartAreas[0].AxisX.Minimum, chart1.ChartAreas[0].AxisX.Maximum);
Microsoft 找到了一个他们为 mscharts 制作的示例项目 here。在使用数据目录中,有一个实时数据部分。他们有一个交互式示例来执行您的要求。为了方便起见,我复制了下面的代码。希望这对您有所帮助。
using System.Windows.Forms.DataVisualization.Charting;
...
private Thread addDataRunner;
private Random rand = new Random();
private System.Windows.Forms.DataVisualization.Charting.Chart chart1;
public delegate void AddDataDelegate();
public AddDataDelegate addDataDel;
...
private void RealTimeSample_Load(object sender, System.EventArgs e)
{
// create the Adding Data Thread but do not start until start button clicked
ThreadStart addDataThreadStart = new ThreadStart(AddDataThreadLoop);
addDataRunner = new Thread(addDataThreadStart);
// create a delegate for adding data
addDataDel += new AddDataDelegate(AddData);
}
private void startTrending_Click(object sender, System.EventArgs e)
{
// Disable all controls on the form
startTrending.Enabled = false;
// and only Enable the Stop button
stopTrending.Enabled = true;
// Predefine the viewing area of the chart
minValue = DateTime.Now;
maxValue = minValue.AddSeconds(120);
chart1.ChartAreas[0].AxisX.Minimum = minValue.ToOADate();
chart1.ChartAreas[0].AxisX.Maximum = maxValue.ToOADate();
// Reset number of series in the chart.
chart1.Series.Clear();
// create a line chart series
Series newSeries = new Series( "Series1" );
newSeries.ChartType = SeriesChartType.Line;
newSeries.BorderWidth = 2;
newSeries.Color = Color.OrangeRed;
newSeries.XValueType = ChartValueType.DateTime;
chart1.Series.Add( newSeries );
// start worker threads.
if ( addDataRunner.IsAlive == true )
{
addDataRunner.Resume();
}
else
{
addDataRunner.Start();
}
}
private void stopTrending_Click(object sender, System.EventArgs e)
{
if ( addDataRunner.IsAlive == true )
{
addDataRunner.Suspend();
}
// Enable all controls on the form
startTrending.Enabled = true;
// and only Disable the Stop button
stopTrending.Enabled = false;
}
/// Main loop for the thread that adds data to the chart.
/// The main purpose of this function is to Invoke AddData
/// function every 1000ms (1 second).
private void AddDataThreadLoop()
{
while (true)
{
chart1.Invoke(addDataDel);
Thread.Sleep(1000);
}
}
public void AddData()
{
DateTime timeStamp = DateTime.Now;
foreach ( Series ptSeries in chart1.Series )
{
AddNewPoint( timeStamp, ptSeries );
}
}
/// The AddNewPoint function is called for each series in the chart when
/// new points need to be added. The new point will be placed at specified
/// X axis (Date/Time) position with a Y value in a range +/- 1 from the previous
/// data point's Y value, and not smaller than zero.
public void AddNewPoint( DateTime timeStamp, System.Windows.Forms.DataVisualization.Charting.Series ptSeries )
{
double newVal = 0;
if ( ptSeries.Points.Count > 0 )
{
newVal = ptSeries.Points[ptSeries.Points.Count -1 ].YValues[0] + (( rand.NextDouble() * 2 ) - 1 );
}
if ( newVal < 0 )
newVal = 0;
// Add new data point to its series.
ptSeries.Points.AddXY( timeStamp.ToOADate(), rand.Next(10, 20));
// remove all points from the source series older than 1.5 minutes.
double removeBefore = timeStamp.AddSeconds( (double)(90) * ( -1 )).ToOADate();
//remove oldest values to maintain a constant number of data points
while ( ptSeries.Points[0].XValue < removeBefore )
{
ptSeries.Points.RemoveAt(0);
}
chart1.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddMinutes(2).ToOADate();
chart1.Invalidate();
}
/// Clean up any resources being used.
protected override void Dispose( bool disposing )
{
if ( (addDataRunner.ThreadState & ThreadState.Suspended) == ThreadState.Suspended)
{
addDataRunner.Resume();
}
addDataRunner.Abort();
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
...
Finally I found solution for my problem with little bit modifications for the code.Thanks for your support.I implemented a line chart with two series and the chart has to display 1 minute data in every frame.
int viewcount=0,count=0,mviewcount=60;
public void AddData() // executing using thread
{
while (true)
{
if (flag) // making flag as true by calling timer for every 1sec
{
flag = false;
DateTime timeStamp = DateTime.Now;
double y1 = 0.0;
double y2= 0.0;
y1= gety1(count);
y2= gety2(count + 1);
AddNewPoint(timeStamp, chart1.Series[0], chart1.Series[1], oilvalue, tempvalue);
count++;
}
Thread.Sleep(1);
}
}
public void AddNewPoint(DateTime timeStamp, System.Windows.Forms.DataVisualization.Charting.Series ptSeries1, System.Windows.Forms.DataVisualization.Charting.Series ptSeries2, double y1, double y2)
{
if (this.chart1.InvokeRequired)
{
BeginInvoke((Action)(() =>
{
this.chart1.Series[0].Points.AddXY(timeStamp.ToOADate(), y1);
this.chart1.Series[1].Points.AddXY(timeStamp.ToOADate(), y2);
if ((count % 60) == 0)
{
mviewcount += 60;
viewcount += 60;
chart1.ChartAreas[0].AxisX.Minimum = DateTime.FromOADate(ptSeries1.Points[count - 1].XValue).ToOADate();
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries1.Points[count - 1].XValue).AddMinutes(1).ToOADate();
min = chart1.ChartAreas[0].AxisX.Minimum;
max = chart1.ChartAreas[0].AxisX.Maximum;
}
if (count >= 60)
{
if ((count >= viewcount) || (count <= mviewcount))
{
chart1.Series[0].Points[0].AxisLabel = System.DateTime.FromOADate(chart1.Series[0].Points[count - 1].XValue).ToString();
chart1.ChartAreas[0].AxisX.ScaleView.Position = max;
}
}
chart1.Update();
chart1.ChartAreas[0].RecalculateAxesScale();
}));
}
}
我在工作.. 60 分钟实时。
if (this.chart1.InvokeRequired)
{
BeginInvoke((Action)(() =>
{
if (!chartState) return;
DateTime now = DateTime.Now;
chart1.ResetAutoValues();
for (int i = 0; i < chart1.Series.Count; i++)
{
if (chart1.Series[i].Points.Count > 0)
{
while (chart1.Series[i].Points[0].XValue < now.AddMinutes(-60).ToOADate())
{
chart1.Series[i].Points.RemoveAt(0);
chart1.ChartAreas[0].AxisX.Minimum = chart1.Series[i].Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = now.AddMinutes(1).ToOADate();
}
}
}
chart1.Series["Sebeke"].Points.AddXY(now.ToOADate(), AnlikSebeke);
chart1.Series["Turbin"].Points.AddXY(now.ToOADate(), AnlikTurbin);
chart1.Series["Tuketim"].Points.AddXY(now.ToOADate(), AnlikTuketim);
chart1.Invalidate();
}));
}
我试图在我的 windows 应用程序中绘制一个包含每一秒实时数据的折线图。为此,我需要为图表设置最小值(0 秒)和最大值(10 分钟)。 10 分钟后,最小值为 10 分钟,最大值为 20 分钟。所以我每次都必须显示10分钟的数据。我需要从一开始就用滚动条显示以前的数据。我尝试了以下代码,但无法设置 chart.Please 的最小值和最大值解决了我的问题。
series1.XValueType = ChartValueType.DateTime;
series1.IsXValueIndexed = true;
series1.YAxisType = AxisType.Primary;
series1.ChartType = SeriesChartType.Line;
this.chart1.Series.Add(series1);
series2.XValueType = ChartValueType.DateTime;
series2.IsXValueIndexed = true;
series2.YAxisType = AxisType.Secondary;
series2.ChartType = SeriesChartType.Line;
this.chart1.Series.Add(series2);
chart1.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss";
chart1.ChartAreas[0].CursorX.IntervalType = DateTimeIntervalType.Seconds;
chart1.ChartAreas[0].CursorX.AutoScroll = true;
chart1.ChartAreas[0].CursorY.AutoScroll = true;
chart1.ChartAreas[0].AxisX.ScrollBar.Size = 15;
chart1.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All;
chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = false;
chart1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisY2.ScaleView.Zoomable = true;
chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
DateTime minValue, maxValue;
minValue = DateTime.Now;
maxValue = minValue.AddSeconds(600);
chart1.ChartAreas[0].AxisX.Minimum = minValue.ToOADate();
chart1.ChartAreas[0].AxisX.Maximum = maxValue.ToOADate();
chart1.ChartAreas[0].AxisX.ScaleView.Zoom(chart1.ChartAreas[0].AxisX.Minimum, chart1.ChartAreas[0].AxisX.Maximum);
Microsoft 找到了一个他们为 mscharts 制作的示例项目 here。在使用数据目录中,有一个实时数据部分。他们有一个交互式示例来执行您的要求。为了方便起见,我复制了下面的代码。希望这对您有所帮助。
using System.Windows.Forms.DataVisualization.Charting;
...
private Thread addDataRunner;
private Random rand = new Random();
private System.Windows.Forms.DataVisualization.Charting.Chart chart1;
public delegate void AddDataDelegate();
public AddDataDelegate addDataDel;
...
private void RealTimeSample_Load(object sender, System.EventArgs e)
{
// create the Adding Data Thread but do not start until start button clicked
ThreadStart addDataThreadStart = new ThreadStart(AddDataThreadLoop);
addDataRunner = new Thread(addDataThreadStart);
// create a delegate for adding data
addDataDel += new AddDataDelegate(AddData);
}
private void startTrending_Click(object sender, System.EventArgs e)
{
// Disable all controls on the form
startTrending.Enabled = false;
// and only Enable the Stop button
stopTrending.Enabled = true;
// Predefine the viewing area of the chart
minValue = DateTime.Now;
maxValue = minValue.AddSeconds(120);
chart1.ChartAreas[0].AxisX.Minimum = minValue.ToOADate();
chart1.ChartAreas[0].AxisX.Maximum = maxValue.ToOADate();
// Reset number of series in the chart.
chart1.Series.Clear();
// create a line chart series
Series newSeries = new Series( "Series1" );
newSeries.ChartType = SeriesChartType.Line;
newSeries.BorderWidth = 2;
newSeries.Color = Color.OrangeRed;
newSeries.XValueType = ChartValueType.DateTime;
chart1.Series.Add( newSeries );
// start worker threads.
if ( addDataRunner.IsAlive == true )
{
addDataRunner.Resume();
}
else
{
addDataRunner.Start();
}
}
private void stopTrending_Click(object sender, System.EventArgs e)
{
if ( addDataRunner.IsAlive == true )
{
addDataRunner.Suspend();
}
// Enable all controls on the form
startTrending.Enabled = true;
// and only Disable the Stop button
stopTrending.Enabled = false;
}
/// Main loop for the thread that adds data to the chart.
/// The main purpose of this function is to Invoke AddData
/// function every 1000ms (1 second).
private void AddDataThreadLoop()
{
while (true)
{
chart1.Invoke(addDataDel);
Thread.Sleep(1000);
}
}
public void AddData()
{
DateTime timeStamp = DateTime.Now;
foreach ( Series ptSeries in chart1.Series )
{
AddNewPoint( timeStamp, ptSeries );
}
}
/// The AddNewPoint function is called for each series in the chart when
/// new points need to be added. The new point will be placed at specified
/// X axis (Date/Time) position with a Y value in a range +/- 1 from the previous
/// data point's Y value, and not smaller than zero.
public void AddNewPoint( DateTime timeStamp, System.Windows.Forms.DataVisualization.Charting.Series ptSeries )
{
double newVal = 0;
if ( ptSeries.Points.Count > 0 )
{
newVal = ptSeries.Points[ptSeries.Points.Count -1 ].YValues[0] + (( rand.NextDouble() * 2 ) - 1 );
}
if ( newVal < 0 )
newVal = 0;
// Add new data point to its series.
ptSeries.Points.AddXY( timeStamp.ToOADate(), rand.Next(10, 20));
// remove all points from the source series older than 1.5 minutes.
double removeBefore = timeStamp.AddSeconds( (double)(90) * ( -1 )).ToOADate();
//remove oldest values to maintain a constant number of data points
while ( ptSeries.Points[0].XValue < removeBefore )
{
ptSeries.Points.RemoveAt(0);
}
chart1.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddMinutes(2).ToOADate();
chart1.Invalidate();
}
/// Clean up any resources being used.
protected override void Dispose( bool disposing )
{
if ( (addDataRunner.ThreadState & ThreadState.Suspended) == ThreadState.Suspended)
{
addDataRunner.Resume();
}
addDataRunner.Abort();
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
...
Finally I found solution for my problem with little bit modifications for the code.Thanks for your support.I implemented a line chart with two series and the chart has to display 1 minute data in every frame.
int viewcount=0,count=0,mviewcount=60;
public void AddData() // executing using thread
{
while (true)
{
if (flag) // making flag as true by calling timer for every 1sec
{
flag = false;
DateTime timeStamp = DateTime.Now;
double y1 = 0.0;
double y2= 0.0;
y1= gety1(count);
y2= gety2(count + 1);
AddNewPoint(timeStamp, chart1.Series[0], chart1.Series[1], oilvalue, tempvalue);
count++;
}
Thread.Sleep(1);
}
}
public void AddNewPoint(DateTime timeStamp, System.Windows.Forms.DataVisualization.Charting.Series ptSeries1, System.Windows.Forms.DataVisualization.Charting.Series ptSeries2, double y1, double y2)
{
if (this.chart1.InvokeRequired)
{
BeginInvoke((Action)(() =>
{
this.chart1.Series[0].Points.AddXY(timeStamp.ToOADate(), y1);
this.chart1.Series[1].Points.AddXY(timeStamp.ToOADate(), y2);
if ((count % 60) == 0)
{
mviewcount += 60;
viewcount += 60;
chart1.ChartAreas[0].AxisX.Minimum = DateTime.FromOADate(ptSeries1.Points[count - 1].XValue).ToOADate();
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries1.Points[count - 1].XValue).AddMinutes(1).ToOADate();
min = chart1.ChartAreas[0].AxisX.Minimum;
max = chart1.ChartAreas[0].AxisX.Maximum;
}
if (count >= 60)
{
if ((count >= viewcount) || (count <= mviewcount))
{
chart1.Series[0].Points[0].AxisLabel = System.DateTime.FromOADate(chart1.Series[0].Points[count - 1].XValue).ToString();
chart1.ChartAreas[0].AxisX.ScaleView.Position = max;
}
}
chart1.Update();
chart1.ChartAreas[0].RecalculateAxesScale();
}));
}
}
我在工作.. 60 分钟实时。
if (this.chart1.InvokeRequired)
{
BeginInvoke((Action)(() =>
{
if (!chartState) return;
DateTime now = DateTime.Now;
chart1.ResetAutoValues();
for (int i = 0; i < chart1.Series.Count; i++)
{
if (chart1.Series[i].Points.Count > 0)
{
while (chart1.Series[i].Points[0].XValue < now.AddMinutes(-60).ToOADate())
{
chart1.Series[i].Points.RemoveAt(0);
chart1.ChartAreas[0].AxisX.Minimum = chart1.Series[i].Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = now.AddMinutes(1).ToOADate();
}
}
}
chart1.Series["Sebeke"].Points.AddXY(now.ToOADate(), AnlikSebeke);
chart1.Series["Turbin"].Points.AddXY(now.ToOADate(), AnlikTurbin);
chart1.Series["Tuketim"].Points.AddXY(now.ToOADate(), AnlikTuketim);
chart1.Invalidate();
}));
}