質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

1回答

2166閲覧

VB.NETのChartコントロールで描画したグラフ上でクリックした位置を始点とした一定長さの直線を描きたい

hydi

総合スコア8

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2022/11/29 10:10

編集2022/12/05 12:09

前提

VisualStudio2022(64bit)のVB.NETにて波形の減衰現象を数値化するプログラムを作っています。
時系列の振動データはCSVで別途用意されています。
CSVを読み込んでLINE描画した後、任意の位置でマウスクリックしその位置を取得して、その位置から一定の時間(ここでは0.2秒)経った2点目のデータを設定して、ソースとは異なるデータセットを作ります。そして2点を結ぶ直線を基準ラインとしてChart1に描く。

実現したいこと

ユーザー側が適切に基準ラインを設定できるように、ビジュアル的に訴えたい。

発生している問題・エラーメッセージ

最初に読み込んだ振動データと軸名が競合して、以下のエラーメッセージが出ます。
バンドルされていない例外;System.ArgumentException: ''B' という名前のグラフ要素が既に 'SeriesCollection' に存在します。
直線データの系列名を変更しても同様のエラーとなります。
どうすればSeries()を区別できるのでしょうか。
.Net初学者でありどう解決すべきか悩んでいます。解決策をご教授いただけると幸いです。

該当のソースコード

Form1にButton1(データ取得),Button2(Click位置取得),Checkbox1(START),Checkbox2(END), Label1(始点時間),Label2(終点時間),Label3(始点のY値),Chart1を貼り付けて以下のソースを実行ください。
CSVファイルのPathは使用環境に合わせて直してください。

該当のソースコード

VB.NET (VS2022)
ソースコード
Imports System.Reflection.Emit
Imports System.Windows.Forms.DataVisualization.Charting
Imports System.Windows.Forms.VisualStyles.VisualStyleElement.Button

Public Class Form1
Dim enc_sjis As System.Text.Encoding = System.Text.Encoding.GetEncoding("sjis")
Dim FileSavePath As String = "C:\Users\cst\Desktop\STR.tmp"
Dim TmpFilePath As String = "C:\Users\cst\Desktop\MS.tmp"
Dim Line_data(1) As String
Dim Range_Start As Integer = 1

Private Sub Read_Chart(Gain_Clic As Integer) Dim ds As New DataSet Using cn As New System.Data.OleDb.OleDbConnection Dim FolderPath As String = Application.StartupPath() cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FolderPath & ";Extended Properties=""Text;HDR=YES;IMEX=1;FMT=Delimited""" Using da As System.Data.OleDb.OleDbDataAdapter = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM " & FileSavePath, cn) da.Fill(ds, "Table1") End Using End Using With Chart1 Select Case Gain_Clic Case 0 '最初に描画するグラフ .Series.Clear() Case 1 End Select .DataSource = ds Dim colum As Integer = ds.Tables(0).Columns.Count - 1 Debug.Print(Chart1.ProductVersion) For i = 1 To colum Dim columnName As String = ds.Tables(0).Columns(i).ColumnName.ToString() .Series.Add(columnName) .Series(columnName).ChartType = DataVisualization.Charting.SeriesChartType.Line .Series(columnName).XValueMember = ds.Tables(0).Columns(0).ColumnName.ToString() .Series(columnName).YValueMembers = columnName .Series(columnName).Color = Color.Red .Series(columnName).BorderWidth = 2 .Series(columnName).MarkerStyle = MarkerStyle.Circle .Series(columnName).MarkerSize = 2 .Series(columnName).MarkerColor = Color.Red Next End With With Chart1.ChartAreas(0).AxisX .IsMarginVisible = False .Minimum = 0 .Maximum = 1 .Interval = 1 End With Dim sv As AxisScaleView = Chart1.ChartAreas(0).AxisX.ScaleView Dim sh As AxisScaleView = Chart1.ChartAreas(0).AxisY.ScaleView With sv .SmallScrollSize = 3 .Position = 0 .Size = 1 End With End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim Gain_Click As Integer = 0 Read_Chart(Gain_Click) End Sub '********************************************************************* Private Sub Chart1_MouseClick(ByVal sender As Object, ByVal e As _ System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseClick Dim Gain_Click As Integer = 1 'マウス位置取得ボタンを押した事実 Dim htrResult As HitTestResult = Chart1.HitTest(e.X, e.Y) If htrResult.ChartElementType = ChartElementType.DataPoint And frgElement = True Then Dim i As Integer = htrResult.PointIndex Dim dp As DataPoint = htrResult.Series.Points(i) For j As Integer = 0 To Chart1.Series.Count - 1 If Chart1.Series(j).Name = htrResult.Series.Name Then Exit For End If Next Select Case Range_Start Case 1 MessageBox.Show(String.Format("{0}{1}({2}秒) : {3}", "始点 ", htrResult.Series.Name, dp.XValue, dp.YValues(0))) Me.Label1.Text = dp.XValue Me.Label1.Visible = True Me.Label2.Text = dp.YValues(0) Chart_Line(dp.XValue, dp.YValues(0)) Case 2 MessageBox.Show(String.Format("{0}{1}({2}秒) : {3}", "終点 ", htrResult.Series.Name, dp.XValue, dp.YValues(0))) Me.Label3.Text = dp.XValue Me.Label3.Visible = True End Select End If End Sub Private frgElement As Boolean Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click frgElement = Not frgElement End Sub Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged Select Case CheckBox1.Checked Case False : CheckBox2.Checked = True : Range_Start = 2 Case True : CheckBox2.Checked = False : Range_Start = 1 End Select End Sub Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged Select Case CheckBox2.Checked Case False : CheckBox1.Checked = True : Range_Start = 1 Case True : CheckBox1.Checked = False : Range_Start = 2 End Select End Sub Private Sub Chart_Line(XValue As Double, YValue As Double) Using sw As New System.IO.StreamWriter(TmpFilePath, False, enc_sjis) Line_data(1) = "C, D" sw.WriteLine(Line_data(0)) Line_data(1) = CStr(XValue) + "," + CStr(YValue) sw.WriteLine(Line_data(1)) Line_data(1) = CStr(XValue + 0.2) + "," + CStr(YValue) '0.2秒分の直線 sw.WriteLine(Line_data(1)) End Using Dim Gain_Click As Integer = 1 Read_Chart(Gain_Click) End Sub

End Class
********************** 以下CSVファイル

  1. ファイル名STR.tmp

A, B
000.000,-4.323925E-03
000.002,-1.741046E-03
000.004,+7.446296E-04
000.006,+7.143901E-03
000.008,+8.835744E-03
000.010,+1.600832E-02
000.012,+1.914202E-02
000.014,+2.442118E-02
000.016,+2.928610E-02
000.018,+3.405155E-02
000.020,+3.583118E-02
000.022,+4.379288E-02
000.024,+4.730390E-02
000.026,+5.360145E-02
000.028,+5.653622E-02
000.030,+6.002408E-02
000.032,+6.478954E-02
000.034,+7.070053E-02
000.036,+7.710677E-02
000.038,+8.005774E-02
000.040,+8.764438E-02
000.042,+9.547873E-02
000.044,+1.108488E-01
000.046,+1.278276E-01
000.048,+1.473869E-01
000.050,+1.708807E-01
000.052,+1.970524E-01
000.054,+2.293757E-01
000.056,+2.663998E-01
000.058,+3.033104E-01
000.060,+3.406677E-01
000.062,+3.805662E-01
000.064,+4.244803E-01
000.066,+4.710188E-01
000.068,+5.167660E-01
000.070,+5.645220E-01
000.072,+6.143378E-01
000.074,+6.682503E-01
000.076,+7.227206E-01
000.078,+7.774362E-01
000.080,+8.284395E-01
000.082,+8.866729E-01
000.084,+9.362781E-01
000.086,+9.823214E-01
000.088,+1.024254E+00
000.090,+1.067108E+00
000.092,+1.105607E+00
000.094,+1.145704E+00
000.096,+1.179330E+00
000.098,+1.209789E+00
000.100,+1.234551E+00
000.102,+1.256626E+00
000.104,+1.274410E+00
000.106,+1.288936E+00
000.108,+1.294298E+00
000.110,+1.298409E+00
000.112,+1.298781E+00
000.114,+1.295314E+00
000.116,+1.287096E+00
000.118,+1.272103E+00
000.120,+1.256680E+00
000.122,+1.237319E+00
000.124,+1.219338E+00
000.126,+1.192510E+00
000.128,+1.168490E+00
000.130,+1.140321E+00
000.132,+1.116328E+00
000.134,+1.090839E+00
000.136,+1.064066E+00
000.138,+1.033645E+00
000.140,+1.006376E+00
000.142,+9.770801E-01
000.144,+9.527785E-01
000.146,+9.228436E-01
000.148,+8.931148E-01
000.150,+8.654272E-01
000.152,+8.410817E-01
000.154,+8.154123E-01
000.156,+7.906155E-01
000.158,+7.665915E-01
000.160,+7.425028E-01
000.162,+7.241585E-01
000.164,+7.055112E-01
000.166,+6.891227E-01
000.168,+6.676980E-01
000.170,+6.550496E-01
000.172,+6.370501E-01
000.174,+6.286717E-01
000.176,+6.181896E-01
000.178,+6.080316E-01
000.180,+5.993571E-01
000.182,+5.969040E-01
000.184,+5.900811E-01
000.186,+5.908402E-01
000.188,+5.872806E-01
000.190,+5.885118E-01
000.192,+5.891970E-01
000.194,+5.925366E-01
000.196,+5.952932E-01
000.198,+5.969064E-01
000.200,+6.012435E-01
000.202,+5.998525E-01
000.204,+5.991907E-01
000.206,+5.868501E-01
000.208,+5.758382E-01
000.210,+5.580934E-01
000.212,+5.387863E-01
000.214,+5.162366E-01
000.216,+4.895281E-01
000.218,+4.542051E-01
000.220,+4.170861E-01
000.222,+3.807425E-01
000.224,+3.414945E-01
000.226,+2.998740E-01
000.228,+2.554462E-01
000.230,+2.091968E-01
000.232,+1.628966E-01
000.234,+1.143190E-01
000.236,+6.331808E-02
000.238,+8.989073E-03
000.240,-4.539551E-02
000.242,-9.562819E-02
000.244,-1.536788E-01
000.246,-1.987038E-01
000.248,-2.452240E-01
000.250,-2.851410E-01
000.252,-3.235052E-01
000.254,-3.548611E-01
000.256,-3.884899E-01
000.258,-4.165107E-01
000.260,-4.428027E-01
[EOF]

  1. ファイル名MS.tmp

A, B
0.044, 0.1413222
0.244, 0.1413222
[EOF]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hydi

2022/11/30 09:25

!!! 凄い~ 頭が柔らかいなぁ~!!! そういう手もあるんですか、試してみます。結果がでたらここで報告します。まずは御礼まで。
hydi

2022/12/02 08:02

いろいろ四苦八苦しておりますが、Chartにすべて任せて、マウスのクリック座標をデータセットに追加し再描画する手法が一応うまくいきましたが、とんでもなく重い動作になって実用にはなりませんでした。ご提案いただいた手法から発展して、CustomePaintイベントを使った手法にたどり着いております。なんとなくですが行けそうな気がします。まずは状況報告まで。https://docs.devexpress.com/WindowsForms/DevExpress.XtraCharts.ChartControl.CustomPaint
KOZ6.0

2022/12/02 09:25

ああ、Chart を再描画すると重くなるんですね。 こんな方法だとどうでしょう? (1) ユーザが操作する部分は PictureBox にして、Chart は PictureBox の下に隠す。(非表示にしてもいいかもしれない) (2) Chart が書き換わったら DrawToBitmap で Bitmap に保存し、PictureBox の BackgroundImage にセット あとは前出のURLのようにユーザの操作を描く
hydi

2022/12/04 02:52

ストーリーは理解しましたが、始点をクリックしPictureBoxで描画した後、PictureBox上で終点をクリックすると、瞬時にChartに切り替わって、Chart上のクリック位置が読めるのかが課題になるように感じます。MS.CHARTに限界を感じますので、もっと自由度の高いChartツールがあったらなぁと思うのです。もしご存じでしたら教えていただきたいです。
KOZ6.0

2022/12/04 06:01 編集

PicureBox を Chart と同じ大きさ、同じ位置にかぶせてしまえば、PictureBox のクリック位置 = Chart のクリック位置になりますね。 そのまま HitTest すればOKでしょう。 他の Chart ツールは知りません。
hydi

2022/12/04 06:06

KOZ6.0さん、何度も返事をありがとうございます。なるほど同一形状のPictureBoxなら終点座標の位置は換算可能。さらにはダブルクリックさせて1度目のクリックでPictureBoxを消して2度目のクリックでChartの座標が読めますね。ヒント”かぶせる’で思ったのですが、もしかすると同じChartに再描画したことで重くなったのかもしれないと。試しにChart2を被せてみようかと思います。
KOZ6.0

2022/12/04 11:40

>PictureBoxを消して2度目のクリックでChartの座標が読めますね。 PictureBox を消す意味がわからないです。 PictureBox のイベントで入ってくるマウスの座標をそのまま Chart コントロールに HitTest すればいいんですが・・・
hydi

2022/12/04 12:33

そういうことですか、頑張ってみます。
hydi

2022/12/05 04:19

PictureBoxと同じコンセプトでChartをもう一枚(Chart2)貼り付けることで描画スピードが大幅に改善して希望が叶いました。コードの変更も最小限だったのでPuctureBoxは採用しませんでしたが、ご指摘いただいたコンセプトを利用したことで解決できました。どうもありがとうございました。
guest

回答1

0

自己解決

ご提案いただいたPictureBoxの利用を検討し、ChartとPictureBoxの2枚を用意するというコンセプトはうまくいく予感がしました。結果、類似手法ですが、Chartに再描画するのではなく、2枚目のChartに複合グラフを描画することによっても実用速度が達成できました。また最小限のコード変更で済ませることもできました。お手数をお掛けしました。

投稿2022/12/05 08:42

hydi

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問