memo

プログラミング備忘録

【C#】Chart折れ線グラフ2

前回の続き
shinopikapi.hateblo.jp


todo
1. 折れ線
2. 1000msec毎にグラフが更新
3. データ数は10、最大100、最小0とする
4. 新しいデータは右側、前のデータはどんどん左側に移動するように表示
5. 表示するデータは、3の範囲で設定した乱数

1-3までは大体完了したので、4,5に取り掛かります。

コンストラクタでTimerの設定をしておいて、Timerイベントを定期的に呼び出します。
以下の関数の中で0-100の範囲で乱数を作成し、作成した関数updateChartでChartを4のように更新していきます。

        private void timer1_Tick(object sender, EventArgs e)
        {
            // 0-100で乱数
            // Random m_r1 = new Random();
            int add = m_r1.Next(0, 100);
            updateChart(chart1, m_value, add);
        }

updateChartの中身は以下のような感じ。
Chart表示用配列を作っておき、配列コピーで最新の値AddをChartの一番右に表示するようにしています。

        private void updateChart(Chart chart, int[] val, int Add)
        {
            int[] cpVal = new int[val.Length];

            // cpValの要素0-8に、valの要素1-9までをコピー
            Array.Copy(val, 1, cpVal, 0, val.Length - 1);

            // cpValの要素の末尾に新しく追加したい値を挿入
            cpVal[cpVal.Length - 1] = Add;

            // 元の配列に更新したデータを戻す
            Array.Copy(cpVal, val, val.Length);

            // 一旦Chartデータをクリア
            chart.Series[Name1].Points.Clear();

            // データ設定
            for (int i = 0; i < 10; i++)
            {
                chart.Series[Name1].Points.AddXY(i, val[i]);
            }
        }

Chart表示では、一旦データクリアしてAddXYしています。
配列のように要素指定して値更新出来ないかなと思ったのですが、今のところ探せていません……。
Array.Copyも要素移動する、みたいなこと出来るかもしれませんが探せていないので、とりあえず配列作ってコピーして……みたいなことをしています。


わかりにくいですが、表示した値が左に移動してる図です。

f:id:shinopikapi:20210130204622j:plain
移動前
f:id:shinopikapi:20210130204659j:plain
移動後


ソース全体は、以下のようになっています。

    public partial class Form1 : Form
    {
        const string Name1 = "Bar1";
        const string AreaName1 = "chartArea1";

        private int[] m_value = new int[10];
        Random m_r1 = new Random();

        public Form1()
        {
            // コンストラクタ
            InitializeComponent();

            // chart
            initChart(chart1, SeriesChartType.Line);//折れ線

            // timer
            timer1.Interval = 1000;
            timer1.Enabled = true;
            timer1.Start();
        }

        private void initChart(Chart chart, SeriesChartType type)
        {
            // 初期化
            chart.Series.Clear();
            chart.ChartAreas.Clear();

            // chart設定
            //string Name1 = "Bar1";
            //string AreaName1 = "chartArea1";
            chart.Series.Add(Name1);// Series追加
            chart.ChartAreas.Add(AreaName1);
            chart.Series[Name1].ChartType = type;

            //max, min 目盛設定
            chart.ChartAreas[AreaName1].AxisY.Maximum = 100;
            chart.ChartAreas[AreaName1].AxisY.Minimum = 0;
            chart.ChartAreas[AreaName1].AxisY.Interval = 20;

            // 目盛線ちょっと出てるところがなくなる
            chart.ChartAreas[AreaName1].AxisX.MajorTickMark.Enabled = false;

            // データ設定
            for (int i = 0; i < 10; i++)
            {
                chart.Series[Name1].Points.AddXY(i, i * 10);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // 0-100で乱数
            int add = m_r1.Next(0, 100);
            updateChart(chart1, m_value, add);
        }

        private void updateChart(Chart chart, int[] val, int Add)
        {
            int[] cpVal = new int[val.Length];

            // cpValの要素0-8に、valの要素1-9までをコピー
            Array.Copy(val, 1, cpVal, 0, val.Length - 1);

            // cpValの要素の末尾に新しく追加したい値を挿入
            cpVal[cpVal.Length - 1] = Add;

            // 元の配列に更新したデータを戻す
            Array.Copy(cpVal, val, val.Length);

            // 一旦Chartデータをクリア
            chart.Series[Name1].Points.Clear();

            // データ設定
            for (int i = 0; i < 10; i++)
            {
                chart.Series[Name1].Points.AddXY(i, val[i]);
            }
        }
    }


参考
https://docs.microsoft.com/ja-jp/dotnet/api/system.random.next?view=net-5.0