投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/9/16 11:47:50
シリアル通信云々の話はひとまず横に置いてしまい、
Chart コントロールの使い方をしっかり押さえてしまいましょう。
今の理解状況のまま、両方一緒に組み込もうとしても、
どちらの問題なのか切り分けしにくいと思いますよ。


> シリアル通信で送られてくるデータが常に変化しているので、
「データ」は変化しますが、「系列」は固定なのでは?

追加するのはデータ(Points)であって、系列(Series)では無いですよね。
両者の違いが曖昧になっているのではないでしょうか。


> 青い▪️は、"X-Axis"のデータで、オレンジの●は、"Y-Axis"のデータで間違いありません。
> Dim s = Chart1.Series.Add("X-Axis")
> Dim t = Chart1.Series.Add("Y-Axis")
上記の行を見れば、変数 s が Series 型であり、s.Name が "X-Axis" であることも
想像できますが、それを知っているのは開発した本人だけです。

最初の質問では、いきなり
> s.BorderWidth = 3
などと書かれているだけでしたから、s と t がそれぞれ
何を意図したものであるのかを第三者が想像することは困難です。

系列が明確に決まっているのであれば、こうした変数名に対しては
s ではなく「X-Axis のデータ系列」であることが分かるような名前、
t ではなく「Y-Axis のデータ系列」であることが分かるような名前を
付けることをおすすめします。


> データを「add」しなければと思っています。
データは追加するべきですが、系列はそうではないですよね。

まずは新規フォームを追加して、そこに Button と Chart だけを貼ってみてください。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Chart1.Series.Add("Sample Series")
End Sub


上記を実行すると、1 回目のボタン押下では、凡例エリアに
新しい系列 "Sample Series" が追加されることになります。

しかし再度ボタンを押すと、同じ名称が競合しているために例外で止まってしまいます。
動的に Add する場合は、それぞれに異なる名前を指定せねばなりません。

しかし今回の系列数は不定ではなく、"X-Axis" と "Y-Axis" の 2 つだけであることが
あらかじめ決まっているようですし、プログラムで Add する必要すらないでしょう。
Form_Load 時(あるいはデザイン時)に Series を 2 つだけ用意しておき、
実行時にはそれを使うように書き換えてみてください。それで解決すると思います。


そもそも Chart には Series や Points など、いくつものコレクションがあるわけですが、
どうもそれぞれの違い(あるいは使い方)を理解しきれていないような印象を受けています。

先の回答ではその点を確認してみる(あるいは気付かせる)意味合いも兼ねて、
現状の設定内容を ListBox に出力させて確認させるよう促してみたのですが、
思惑が外れて、確認は後回しにされてしまったようですね…。


それはさておき、蛇足までにそれぞれのコレクションの意味を一応説明しておきますと。

➊【Chart1.ChartAreas】グラフエリア

上記では、一つの Chart コントロール上に、上下に 2 つの ChartArea が設定されています。
(各エリアの描画位置は自動的に調整されますが、明示的にエリアの座標を指定することも可能です)

データをどのエリアにプロットさせるのかは、Series の ChartArea プロパティで指定します。
.ChartAreas.Count が 0 であった場合、Chart コントロール上には何も描画されませんので、
ChartArea は最低一つは割り当てておくようにしてください。

これは通常、デザイン時に指定しておけば十分です。

vb素人さんが先月投稿されたコードでも、
>> Chart1.ChartAreas("ChartArea1")
のようにして、デザイン時に割り当てられた名前(といっても初期値のままですが)でアクセスしていましたよね。

他のコレクションも、同様に名前指定でアクセスできるようになっています。
また先の ListBox でのコードのように、ループ処理でそれらを列挙することもできます。


➋【Chart1.Legends】凡例

Series の Legend プロパティに Legend オブジェクトの名前を設定することで、
データ系統(Series)と凡例を関連付けます。

凡例を一切使わないのであれば、.Legends.Count が 0 の状態であっても構いません。
なお、複数の ChartAreas の凡例を一つの Legend 内ににまとめて表示することも、
一つのグラフの凡例を、複数の Legends に分散して配置することもできます。

これも、デザイン時に指定しておくことが多いです。
もちろんプログラムから作り直しても構いません。どちらにするかは好みの問題ですね。


➌【Chart1.Series】系列

上記では、色違いの 4 本の Series が登録されています。
系列をどのエリアにプロットさせるのかは、Series の ChartArea プロパティで指定します。

各系列は、Line、Spline、Column、Point といった、いずれかの ChartType を持ちます。
一つの CharArea 内に、ChartType の異なる複数の Series を含めることもできます。

たとえば Line グラフの場合、同じ系列上の各マーカーは線で繋がりますが、
異なる系列上のマーカーが繋がることはありません。



➍【Points】プロットするデータ
「Points」は Chart のプロパティではなく、Series のプロパティです。

今更説明するまでもないと思いますが、今回のケースでいえば、
受信したデータを動的に割り当てていく際に使うのがこれです。

今回の場合、前回のプロット結果を
>> Chart1.Series.Clear()   '既存の Series をクリアする場合 
で、自ら抹消してしまっていますよね。

その後で .Series.Add しなおしていますが、先の Clear によって、
それに従う Points も、当然一緒に失われてしまっているわけです。

今回、時間経過で増えていくのは「データ」であって「系列」ではありません。
.Points にデータを追加することはあっても、
.Series に系列を増やす必要なないですよね。

仮に、途中でグラフへの出力結果をクリアしたくなったとしても、
Clear するのは .Points だけで十分すよね。