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

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

新規登録して質問してみよう
ただいま回答率
85.31%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

3545閲覧

c# シリアルポートからの受信データを複数のtextBoxに追加する

yellowcloak

総合スコア2

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

1グッド

0クリップ

投稿2022/04/22 08:22

編集2022/04/24 20:24

ご助言をいただきたくよろしくお願いします
serial通信で受信したデータを表示するGuiを作っています。
下記のようにして受信するところまではできました。 
受信データは64個の温度データです。
これをtextBox1-64にそれぞれ格納するようにしたいのですが、
どのようにしたらいいのかわからず困っています。
dataに格納された文字列型のデータをどのように処理したらいいのかご教示いただいたいです。
for文を使ってデータをそれぞれtextBox1~64へ格納したいです。
そこから何をしていったらいいのかわからず困っております。

dataに入っている中身は”3\r\n23\r\n22\r\n22\r\n22\r\n23\r\n…というように数字(温度)\r\nが64個繋がります。最初の3は固定値です。

private void SerialPort1_DataReceived_1(object sender, SerialDataReceivedEventArgs e) //! シリアルポートをオープンしていない場合、処理を行わない. if (serialPort1.IsOpen == false) { return; } else { string data = string.Empty; try { //受信データの読み取り data = serialPort1.ReadExisting()   } catch (Exception ex) { MessageBox.Show(ex.Message); } AddRecievedDataDelegate add = new AddRecievedDataDelegate(AddRecievedData); this.Invoke(add, data); } } private void AddRecievedData(string data){ textBox1.Text += data; }

ご回答をいただいたもの参考に以下のように変更してみました。
this.Invoke(add, data);のところで
System.NullReferenceException: 'オブジェクト参照がオブジェクト インスタンスに設定されていません。とエラーが出てしまい、今までこのようなことがなかったのですが、どこを修正するとこのエラーが解消できるか悩んでおります。
ご教示いただきたくお願いします。

public partial class Form1 : Form { private TextBox[] txtBoxes; public Form1() { InitializeComponent(); int width = 100; int counter = 0; for (var i = 0; i < 8; i++) { for(var j =0; j < 8; j++) { new TextBox { Name = $"textBox{counter + 1}", Location = new Point(j * width + 70, i * 28 + 30), Size = new Size(20,5), Parent = this, }; new Label { Name = $"testPIXCEL{i + 1}", Text = $"PIXECL{counter+ 1}", Location = new Point(j * width + 6, i * 28 + 30), Size = new Size(60, 15), Parent = this, }; counter++; txtBoxes = new TextBox[counter]; } } } private void Form1_Load(object sender, EventArgs e) { string[] ports = SerialPort.GetPortNames(); foreach (string port in ports) { comboBox1.Items.Add(port); //確認できるCOMポートを取得して表示する。 } if (comboBox1.Items.Count > 0) comboBox1.SelectedIndex = 0; } private delegate void AddRecievedDataDelegate(string data); private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { //! シリアルポートをオープンしていない場合、処理を行わない. if (serialPort1.IsOpen == false) { return; } else { string data = string.Empty; try { //受信データの読み取り data = serialPort1.ReadExisting(); } catch (Exception ex) { MessageBox.Show(ex.Message); } AddRecievedDataDelegate add = new AddRecievedDataDelegate(AddRecievedData); this.Invoke(add, data); } } private void AddRecievedData(string data) { string[] stringdata = new string[] { "\r\n" }; string[] disdata = data.Split(stringdata, StringSplitOptions.None); for(var i =0; i< txtBoxes.Length; i++) { if(i < disdata.Length) { txtBoxes[i].Text = disdata[i]; } else { txtBoxes[i].Text = "---"; } } } private void button1_Click(object sender, EventArgs e) { if (serialPort1.IsOpen == true) { //! シリアルポートをクローズする. serialPort1.Close(); //! ボタンの表示を[切断]から[接続]に変える. button1.Text = "接続"; } else { //! オープンするシリアルポートをコンボボックスから取得 serialPort1.PortName = comboBox1.SelectedItem.ToString(); serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.DataBits = 8; serialPort1.StopBits = StopBits.One; serialPort1.Handshake = Handshake.None; serialPort1.Open(); //! ボタンの表示を[切断]から[接続]に変える. button1.Text = "切断"; } } } } コード
TN8001👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2022/04/22 10:12

> dataに格納された文字列型のデータをどのように処理したらいいのかご教示いただいたいです。 data にはどのようなものが取得できているのか書いてください。
yellowcloak

2022/04/22 12:02

ご連絡ありがとうございます。 dataに入っている中身は”3\r\n23\r\n22\r\n22\r\n22\r\n23\r\n…というように数字(温度)\r\nが64個繋がります。最初の3は固定値です。
退会済みユーザー

退会済みユーザー

2022/04/22 12:05

上記は質問欄を編集して追加情報として追記願います、ここコメント欄は「質問への追記・修正の依頼」ですので。
退会済みユーザー

退会済みユーザー

2022/04/23 23:55

質問者さん、無言ですが、解決したならクローズしてください。まだ質問があればそれを書いてください。無言で放置はマナー違反です。
退会済みユーザー

退会済みユーザー

2022/04/24 14:02 編集

NullReferenceException ぐらいは自分でデバッガを使ってどこに問題があるか切り分けるべき。コードを丸投げしてデバッグしてくれと言うのは回答者に期待しすぎです。どの行で例外がスローされるかさえ書いてないのに・・・
退会済みユーザー

退会済みユーザー

2022/04/25 01:07 編集

デバッグしたのですかね? また無言ですが、デバッガの使い方が分かりませんとか、やったけど分かりませんでしたとかのフィードバックぐらいは返したらいかが? 注文を付けるばかりでは何なので、ヒントを書いておきます。Form1 のコンストラクタのコードをよく見てください。入れ物 txtBoxes を作って new TextBox で入れるものも作ったのですが、入れ物の中に作ったものを入れてないのが問題でしょう。(それ以外にも見直すべき所は多々ありそうですが) 上のヒントで解決しなければ、表題とは話が違ってきているので、このスレッドはクローズして(表題の件は解決したはず)、別に新たにスレッドを作って質問してください。一つの問題の解決が次の疑問をよんで次から次へと質問をするのは避けてください。
yellowcloak

2022/04/25 03:13

ご連絡ありがとうございます。 デバッグしてみました。やったことはデバッグの開始F5で動作させてエラーが発生したのでその内容を解消すべく、ググりました。が、エラー内容から何を言ってるのかイマイチ良くわからず困っている状態です。これがご指摘のデバッグをやったことに入らないのであれば、できてませんが正解になります。 ヒント参考にさせていただきます。
退会済みユーザー

退会済みユーザー

2022/04/25 03:33 編集

フィードバックを返しましょう。でないと、あなたが何をしたのかなんてわからない。 ちなみに、エラーが出る行の少し前の行にブレークポイントを置いて、デバッグ実行してそこで止まったらステップ実行して、変数を調べ、何が null になっているか調べる・・・なんてアドバイスもフィードバックが無ければできないことを認識してください。
退会済みユーザー

退会済みユーザー

2022/04/25 03:35

> ヒント参考にさせていただきます。 上のヒントで解決しなければ、表題とは話が違ってきているので、このスレッドはクローズして(表題の件は解決したはず)、別に新たにスレッドを作って質問してください。一つの問題の解決が次の疑問をよんで次から次へと質問をするのは避けてください。
TN8001

2022/04/25 15:47

> ご回答をいただいたもの参考に以下のように変更してみました。 回答に追記いました。ご確認ください。 ここの通知は来るけど、質問や回答の通知は(今は不具合で)来ないのかな??
退会済みユーザー

退会済みユーザー

2022/04/26 00:57

TN8001 さんと私の回答のヒントで解決しなければ、表題とは話が違ってきているので、このスレッドはクローズして(表題の件は解決したはず)、別に新たにスレッドを作って質問してください。一つの問題の解決が次の疑問をよんで次から次へと質問をするのは避けてください。 ここは質問者専用の Q&A の場ではないのです。Teratail は「teratailは技術に興味のある人達が集まって、質問と回答を通してお互いに知識や情報を交換・共有する場所です。」ということで、その意味でも解決したならクローズするのは質問者の務めです。
guest

回答3

0

ベストアンサー

「多数のTextBoxに値をどう入れたらいいのか」って話ですよね?

よく↓みたいなことがしたい(Unityで多い)って質問があります(もちろんできませんよ^^;

cs

1for(int i = 1; i <= 64; i++) 2{ 3 ("txtBox" + i).Text = "hogehoge"; 4}

「配列かなんかを使いましょう」って回答になるわけですが、例がないとイメージがわかないでしょうからこんな雰囲気という例です。
64個はだいぶ多いので作成もforでやりたいところですが、もう置いてあるのでしょうから探してくる実装です。

.NET 6.0です^^

cs

1using System; 2using System.Drawing; 3using System.Linq; 4using System.Windows.Forms; 5 6namespace Qiiyta0b542pggh 7{ 8 public partial class Form1 : Form 9 { 10 private readonly TextBox[] txtBoxes; 11 private readonly System.Timers.Timer timer; 12 13 public Form1() 14 { 15 InitializeComponent(); 16 17 // 64個は面倒なので6個(デザイナで置いている場合はこのforは不要) 18 for (var i = 0; i < 6; i++) 19 { 20 // 作成もforでやっていれば、わざわざFindで探す必要もないのですが... 21 // txtBoxes[i] = new TextBox 22 new TextBox 23 { 24 Name = $"textBox{i + 1}", 25 Location = new Point(12, i * 37 + 12), 26 Parent = this, 27 }; 28 } 29 30 // 扱いやすいようにTextBoxの配列を用意 31 txtBoxes = new TextBox[6]; 32 for (var i = 0; i < 6; i++) 33 { 34 // textBox1~6を探して配列に格納(見つからなかったら当然エラー) 35 txtBoxes[i] = (TextBox)Controls.Find($"textBox{i + 1}", true).First(); 36 } 37 38 // SerialPortは大変なのでタイマーで代用(Timer_Elapsedも別スレッド) 39 timer = new System.Timers.Timer(1000); 40 timer.Elapsed += Timer_Elapsed; 41 timer.Start(); 42 } 43 44 private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) 45 { 46 //string data = "3\r\n23\r\n22\r\n22\r\n22\r\n23\r\n"; 47 // 特に意味はない(てきとうなデータをでっちあげてるだけ) 48 string data = string.Join("\r\n", DateTime.Now.Ticks.ToString().ToCharArray().Reverse().Select(x => $"{x}")); 49 50 // 改行で分割 51 string[] split = data.Split("\r\n"); 52 53 // UIスレッドで実行 54 Invoke(() => 55 { 56 for (var i = 0; i < txtBoxes.Length; i++) 57 { 58 // データが足りない時があるのかは知りませんが、念のため 59 if (i < split.Length) 60 { 61 txtBoxes[i].Text = split[i]; 62 } 63 else 64 { 65 txtBoxes[i].Text = ""; 66 } 67 } 68 }); 69 } 70 } 71}

AddRecievedDataDelegateって元ネタどこなんですかね?
もちろん当時はそう書くしかなかったんでしょうけど、いまだに「いつの時代の記事!?」みたいなのばっかりで驚きました(Invokeのところの話)

コピペコピペで増殖したにしても、やけに多い気がします(本当に古い記事も多いですが^^;

C# SerialPort DataReceived - Google 検索


編集の通知が来なくて気が付くのが遅れました。

cs

1counter++; 2txtBoxes = new TextBox[counter];

ここは明らかにおかしいです。

cs

1txtBoxes = new TextBox[1]; 2txtBoxes = new TextBox[2]; 3// ・・・

と箱(配列)だけ用意して中身(TextBox)を入れていませんし、何度も無駄に箱だけ作っています。

cs

1public Form1() 2{ 3 InitializeComponent(); 4 5 int width = 100; 6 int counter = 0; 7 8 txtBoxes = new TextBox[8 * 8]; 9 for (var i = 0; i < 8; i++) 10 { 11 for (var j = 0; j < 8; j++) 12 { 13 txtBoxes[counter] = new TextBox 14 { 15 Name = $"textBox{counter + 1}", 16 Location = new Point(j * width + 70, i * 28 + 30), 17 Size = new Size(20, 5), 18 Parent = this, 19 }; 20 new Label 21 { 22 Name = $"testPIXCEL{i + 1}", 23 Text = $"PIXECL{counter + 1}", 24 Location = new Point(j * width + 6, i * 28 + 30), 25 Size = new Size(60, 15), 26 Parent = this, 27 }; 28 29 counter++; 30 } 31 } 32}

こんな感じで箱は1回だけ64個で作り、中身をcounter番目に入れます。

cs

1AddRecievedDataDelegate add = new AddRecievedDataDelegate(AddRecievedData); 2this.Invoke(add, data);

ここも、

cs

1this.Invoke(AddRecievedData, data);

こうでいいはずです。

投稿2022/04/22 14:53

編集2022/09/22 11:27
TN8001

総合スコア10022

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

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

yellowcloak

2022/04/22 22:17

ご回答ありがとうございます。 探してくるという発想はありませんでした。非常に参考になります。ありがとうございます。 ご指摘のAddRecievedDataDelegateですが、いろんなところで参考にして、やってみては動いたな、動かないなのようなことをしており、どこだったのか今では探すことができない状態です。 Invokeのところは確かに2012年の更新されたブログなども参考にさせていただいております。 今は進化しているのですね。 勉強します。
退会済みユーザー

退会済みユーザー

2022/04/22 23:58

> string[] split = data.Split("\r\n"); そのオーバロードは .NET Framework 4.8 とかで使えますか? 質問者さんの環境は書いてないので不明ですけど・・・
TN8001

2022/04/23 00:26 編集

> そのオーバロードは .NET Framework 4.8 とかで使えますか? 使えないですね。 Split(String, StringSplitOptions) [String.Split メソッド (System) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.string.split?view=net-6.0#system-string-split(system-string-system-stringsplitoptions)) 個人的にはもう.NET6完全移行なので、書いていない限り(過去質問もざっとは見ますが).NET Frameworkは使ってないです。 WinFormとかでも不自由はほとんどないですし。 .NET Frameworkならこっちですか。 Split(String[], StringSplitOptions) [String.Split メソッド (System) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.string.split?view=net-6.0#system-string-split(system-string()-system-stringsplitoptions))
TN8001

2022/04/23 00:27

下のリンクが ) がどうしても入んない。どうすりゃいいんだ?w
退会済みユーザー

退会済みユーザー

2022/04/23 00:48

> WinFormとかでも不自由はほとんどないですし。 めっちゃ不自由がありましたけど? 例えば VS2022, .NET 6.0 がリリースされた時でも以下の記事のような。 .NET 6.0 で Windows Forms アプリ作成 http://surferonwww.info/BlogEngine/post/2021/12/04/create-winforms-application-using-visual-studio-2022-net-6.aspx ある程度は改善されたようですが、.NET Framework 版と同じレベルにはなってません。不自由がないというのは TN8001 さんが使う範囲の話ですよね。
退会済みユーザー

退会済みユーザー

2022/04/23 00:55

> 使えないですね。 回答を書き直しませんか? .NET 6.0 で書いていると明記するとか、.NET Framework 4.8 でも .NET 6.0 でも動くように書き直すとか。
TN8001

2022/04/23 01:10 編集

そうですね。「私が回答する範囲では」ってことですね。 デザイナやForm1.resxに関しては改善していると思います。 DataTableとかは使ってないので^^; もちろんうまくいかなかったらFrameworkにすればいいわけで、そろそろ(いいかげん?).NETも使っていかないといつまでたっても移行できなくなりますよね? どんどん使ってバグがあったら、どんどんフィードバックを上げたらいいと思います^^
退会済みユーザー

退会済みユーザー

2022/04/23 01:52

> そろそろ(いいかげん?).NETも使っていかないといつまでたっても移行できなくなりますよね? Windows OS で動く Windows Forms アプリを .NET 6.0 で作る理由は何もないと思いますけど? 他の OS で使うということでも、他の OS がサポートしてないことがあるので(例えば GDI+ とか)、難しそう(少なくとも面倒そう)です。 Windows OS で使うという前提であれば、フレームワークの移行とかいう話についても .NET 6.0 と .NET Framework 4.8 のサポート期間を考えると、.NET Framework 4.8 が選択肢の一番に来ると思っていますが。
TN8001

2022/04/23 10:19

まず断っておきたいのは私自身はアマチュアなので、プロの方とはスタンスが違うという点です。 プロの方が保守的(枯れたものを選ぶ)だったり、サポートの長いものを使いたいということはわかります(私も仕事だったら.NET Frameworkを選ぶかもしれません) しかし質問者は(閲覧者も?)アマチュアが多いでしょうし、どうせなら新しい機能も(新鮮なうちに)どんどん使ってほしいと思って回答しています(プロなら.NET6な回答でもどうとでもできるでしょう) 私自身「回答で初めて使ってみた」ようなこともあります(そのあたりも回答のモチベーションの一つです) SurferOnWwwさんを説得するつもりではないですが、いい点を挙げてみました。 * C#10等の新しい言語機能(.NET Frameworkは既定でC#7.3) 明示的にLangVersionを上げればいいのですが、説明が面倒ですし上げても使えないものもごく一部あります。 * パフォーマンス 個人的には差は体感していませんが、上がった上がったって言ってるので違うんでしょう^^; * 新機能 なぜか.NETでWinFormにも機能強化があったりします。 TaskDialog・ListViewの折りたたみ可能なグループ・既定のフォントあたりは面白そう(便利そう)だと思います。 [Windows フォーム .NET 5 の新機能 - Windows Forms .NET | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/desktop/winforms/whats-new/net50) [Windows フォーム .NET 6 の新機能 - Windows Forms .NET | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/desktop/winforms/whats-new/net60) * 公式ドキュメントも.NET化してきている 「だからどうした?」ですが、これを見てやったって人もでてくるでしょう。 [Visual Studio での新しいアプリの作成に関するチュートリアル - Windows Forms .NET | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/desktop/winforms/get-started/create-app-visual-studio) * SDKスタイルのcsproj .NET Frameworkで作成すると古いcsprojで作成されます(これはテンプレートの問題でしょうからそのうち変わるかもしれませんが) SDKスタイルは編集も楽ですし、何より超すっきりしています( .NETで作っておいてTargetFrameworkをnet48にすることは可能ですし、マルチターゲットにすることもできます) [.NET プロジェクト SDK の概要 | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/core/project-sdk/overview) もちろんいい点ばかりでないのも承知しています。 [Windows フォームに関する破壊的変更 - .NET | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/core/compatibility/winforms) 実は1年前くらいまでは(個人的にはWinFormは使いませんが回答では)WinFormは無条件で.NET Frameworkで作っていました(コンソールやWPFはすでに.NETです) 半年前くらいから気分次第で.NETにしたりしていたのですが、「何の差もなく使えるなぁ」という印象を持ちました(簡単なアプリなので当然ですが^^; [WinFormsアプリの.Net 6.0への移行がうまく行かない](https://teratail.com/questions/9farzvu2hj7z6m) とどめはこの質問で、 * マルチターゲットにすればデザイナの問題も回避できること * .NET Frameworkから.NETに上げるのは結構めんどくさいが、.NETから.NET Frameworkに下げるのは簡単なこと に気が付いたので(少なくとも作成時に).NETを選ばない理由はないなと、つい最近判断したのでした。
退会済みユーザー

退会済みユーザー

2022/04/23 12:21 編集

TN8001 さんがどちらを選ぶかについては何の異論もありませんけど、回答者として回答する場合は話が違うと思います。「個人的にはもう.NET6完全移行」ということでも、質問者がそうとは限らないのでコメントさせていただきました。 ポイントはそこだけだったのですが、 > そろそろ(いいかげん?).NETも使っていかないといつまでたっても移行できなくなりますよね? というレスがあって、それには自分としては賛同しかねるところがありますので、それを書かせてもらった次第です。
TN8001

2022/04/23 12:36

了解しました。 .NETをアピールしたい(.NETでしか使えない機能を使う)ときは注釈をつけるようにしているつもりなのですが、今回のSplitは素で気が付いていませんでした。 いわれてから気が付いた次第です。補足ありがとうございます^^
guest

0

dataに入っている中身は”3\r\n23\r\n22\r\n22\r\n22\r\n23\r\n…というように数字(温度)\r\nが64個繋がります。最初の3は固定値です。

String.Split メソッドを使ってはいかがですか? 以下のような感じ。取得できた String の配列の各要素を TextBox.Text に代入していけば良さそうです。

イメージ説明


【追記】

this.Invoke(add, data);のところで System.NullReferenceException: 'オブジェクト参照がオブジェクト インスタンスに設定されていません。とエラーが出てしまい、今までこのようなことがなかったのですが、どこを修正するとこのエラーが解消できるか悩んでおります。

質問のコメントでも書きましたけど、デバッグはしたのですかね? また無言ですが、デバッガの使い方が分かりませんとか、やったけど分かりませんでしたとかのフィードバックぐらいは返したらいかが?

注文を付けるばかりでは何なので、ヒントを書いておきます。Form1 のコンストラクタのコードをよく見てください。入れ物 txtBoxes を作って new TextBox で入れるものも作ったのですが、入れ物の中に作ったものを入れてないのが問題でしょう。(それ以外にも見直すべき所は多々ありそうですが)

上のヒントで解決しなければ、表題とは話が違ってきているので、このスレッドはクローズして(表題の件は解決したはず)、別に新たにスレッドを作って質問してください。一つの問題の解決が次の疑問をよんで次から次へと質問をするのは避けてください。

投稿2022/04/22 12:19

編集2022/04/25 02:41
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2022/04/22 13:08

マイナス評価をしたのは誰? 理由も書かないのは卑怯者のすること。
guest

0

受信イベント中では別スレッドでの実行となるので、TextBoxで表示しようとすると一工夫必要になります。
そこらへんはぐぐるとやりかたがでてくるので調べてみてください。

投稿2022/04/22 12:03

y_waiwai

総合スコア88163

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

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

dodox86

2022/04/22 23:20

> 受信イベント中では別スレッドでの実行となるので、TextBoxで表示しようとすると一工夫必要になります。 質問者さんの提示コード中、this.Invoke(add, data); となっているので、TextBoxコントロールへのアクセスはthisの属するUIスレッド(FormかWindow?)で行われていると見え、別スレッドでの実行にはならないのでは。つまり、提示コードの範囲では少なくともちゃんと動作する。どのような意図でのご回答か私が把握しかねているのかもしれませんが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問