|
■No79089 (さくらとあおい さん) に返信
こんな感じ?
「参照設定」に、System.Windows.Forms.DataVisualization を追加。
Form の上に FlowLayoutPanel と Chart を置く。
FlowLayoutPanel の上に Button を置く。
「開始する」をクリックすると、スクロールが始まる。
要は、「新しいデータを最後に追加し、最初のデータを削除する」ってこと。
「データを更新する」と「描画する」を別スレッドにしたので、「描画中にデータが更新される」ことを防ぐ必要が出てきてしまった。
using System;
using System.Data;
using System.Windows.Forms;
namespace Wankuma79058
{
public partial class Form1 : Form
{
private System.Threading.Timer dataTimer;
private System.Threading.Timer drawTimer;
private System.Threading.SpinLock locker;
private DataTable dataTable;
private int additionalTime;
private Action drawAction;
public Form1()
{
InitializeComponent();
this.flowLayoutPanel1.Dock = DockStyle.Bottom;
this.flowLayoutPanel1.AutoSize = true;
this.chart1.Dock = DockStyle.Fill;
this.button1.Text = "開始する";
this.button1.Click += this.StartTimer;
this.FormClosing += new FormClosingEventHandler(FormClosingHandler);
this.additionalTime = 0;
this.drawAction = new Action(this.drawGraph);
this.locker = new System.Threading.SpinLock();
this.dataTable = new DataTable();
this.dataTable.Columns.Add("time", typeof(int));
this.dataTable.Columns.Add("data", typeof(float));
for (int i = 0; i < 20; ++i)
{
var row = this.dataTable.NewRow();
row["time"] = (++this.additionalTime);
row["data"] = 0;
this.dataTable.Rows.Add(row);
}
this.chart1.Series.Clear();
var data = this.chart1.Series.Add("data");
data.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.SplineArea;
data.XValueMember = "time";
data.YValueMembers = "data";
this.chart1.DataSource = this.dataTable;
this.dataTimer = new System.Threading.Timer(this.DataTimerCallback, null, System.Threading.Timeout.Infinite, 200);
this.drawTimer = new System.Threading.Timer(this.drawTimerCallback, null, 200, 200);
}
void FormClosingHandler(object sender, FormClosingEventArgs e)
{
this.button1.Enabled = false;
this.dataTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
this.drawTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
}
void StartTimer(object sender, EventArgs e)
{
this.dataTimer.Change(200, 200);
this.button1.Text = "停止する";
this.button1.Click -= this.StartTimer;
this.button1.Click += this.StopTimer;
}
void StopTimer(object sender, EventArgs e)
{
this.dataTimer.Change(System.Threading.Timeout.Infinite, 200);
this.button1.Text = "開始する";
this.button1.Click -= this.StopTimer;
this.button1.Click += this.StartTimer;
}
private void DataTimerCallback(object state)
{
++this.additionalTime;
var row = this.dataTable.NewRow();
row["time"] = this.additionalTime;
row["data"] = Math.Sin(this.additionalTime) + 1;
bool taken = false;
this.locker.Enter(ref taken);
this.dataTable.Rows.Add(row);
this.dataTable.Rows.RemoveAt(0);
if (taken)
{
this.locker.Exit();
}
}
private void drawTimerCallback(object state)
{
if (this.IsDisposed == false)
{
if (this.InvokeRequired)
{
this.Invoke(this.drawAction);
}
else
{
this.drawGraph();
}
}
}
private void drawGraph()
{
bool taken = false;
this.locker.Enter(ref taken);
this.chart1.DataBind();
if (taken)
{
this.locker.Exit();
}
}
}
}
|