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

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

新規登録して質問してみよう
ただいま回答率
85.32%
Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

237閲覧

pythonでシリアル通信の値表示

nonchan1

総合スコア6

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2025/03/27 01:09

実現したいこと

シリアル通信時tkinterでの表示

発生している問題・分からないこと

pythonを使ってシリアル通信を行っています。通信はできるのですが、通信時取得したデータの一部を
tkinterで表示したいのですが、添付したプログラムでは通信終了後タブにデータが表示されてしまいます。
VScodeでterminalでは表示されるのですが、できれば作業者でもわかるように表示をさせたく。
tkinterにはこだわりませんが、詳しくなく。

該当のソースコード

import serial import struct import pandas as pd import time from datetime import datetime from styleframe import tests import tkinter from tkinter import filedialog # 画面作成 root = tkinter.Tk() root.geometry('400x450') # 横x縦 root.title('エクセルファイル保存名指定') measuretime = ['' for i in range(1,6100)] STATE = ['' for i in range(1,6100)] ser = serial.Serial("COM3", 19200) for k in range(60): current_time = datetime.now() measuretime[k] = current_time.strftime("%Y/%m/%d %H:%M:%S.%f")[:-3] send4 = 'AAC81205112233445566778855' ser.write(send4.encode()) recv4 = ser.read(13) unrecv4 = struct.unpack('sssssssssssss',recv4) state1=(unrecv4[8])[-1] #2進数化 state2=bin(state1) #2進数化 STATE[k]= state2[2:6] time.sleep(0.01) la = tkinter.Label(root, text=STATE, font=("Arial", '12')) la.place(x= 100, y= 350) la.pack() ser.close() root.mainloop() # アプリを起動

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

それらしきものは見つかりませんでした。

補足

通信終了後タブにデータが表示されてしまいます。

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

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

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

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

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

guest

回答3

0

tkinter.Tk.after() を利用して、0.01秒毎にシリアルポートからデータを読み込む方法が考えられます。(表示にはラベルではなく、scrolledtext.ScrolledText の方がよいかもしれません)

python

1import serial 2import struct 3import time 4import tkinter 5from datetime import datetime 6 7class SerialData: 8 def __init__(self): 9 self.measuretime = ['' for i in range(1, 6100)] 10 self.STATE = ['' for i in range(1, 6100)] 11 self.send4 = 'AAC81205112233445566778855' 12 self.ser = serial.Serial('COM3', 19200) 13 self.nth = 0 14 self.N = 60 15 16 def read(self): 17 if self.nth >= self.N: 18 if (self.ser.isOpen()): 19 self.ser.close() 20 return 21 global root, la 22 current_time = datetime.now() 23 self.measuretime[self.nth] = current_time.strftime("%Y/%m/%d %H:%M:%S.%f")[:-3] 24 self.ser.write(self.send4.encode()) 25 recv4 = self.ser.read(13) 26 unrecv4 = struct.unpack('sssssssssssss', recv4) 27 state1 = (unrecv4[8])[-1] # 2進数化 28 state2 = bin(state1) # 2進数化 29 # update label text 30 la['text'] += state2[2:6] + '\n' 31 self.nth += 1 32 root.after(10, self.read) 33 34# 画面作成 35root = tkinter.Tk() 36root.geometry('400x450') # 横x縦 37root.title('エクセルファイル保存名指定') 38la = tkinter.Label(root, text='', font=('Arial', '12')) 39la.place(x=100, y=350) 40la.pack() 41 42# read data from serial port 43serial_data = SerialData() 44root.after(10, serial_data.read) 45root.mainloop()

投稿2025/03/27 02:57

編集2025/03/27 03:57
melian

総合スコア21054

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

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

0

ベストアンサー

コードにつっこみどころはいくつかありますがちょっとだけアドバイスです。

現状の処理では、通信処理がすべて終った後に、GUIの処理の起動(メインループ)を起動しているので、通信の状況を表示するにはGUIを動かしながら通信するようにする必要があります。なのでまずは、2つのことをしなければなりません。

  1. 通信処理をメインループから呼ぶようにする。
  2. 通信処理中に画面が更新されるようにする。

1 については、全部説明すると大変なので方式だけ

  • 通信処理を関数化します。
  • 画面にボタンなどを配置し、そのボタンが押されたらその関数を実施=通信を実施するようにする

2については、以下の場所に画面を更新する処理を入れれば表示されるようになります。

python

1 2 la = tkinter.Label(root, text=STATE, font=("Arial", '12')) 3 la.place(x= 100, y= 350) 4 la.pack() 5 root.update_idletasks() # これを挿入

ただし、この処理では、60回のループごとに新しくラベルを作って同じ場所に表示しているので、結果として見えないラベルが大量に生成/表示されてしまいます。
ラベルの作成はループの外(root画面を作った後あたり)で行ない、このタイミングではラベルのテキストの変更だけ行なうのがいいでしょう。


「update_idletasks()」はメインループ(root.mainloop())の外で画面の更新をするためのメソッドですが、GUIアプリの作法としてはあまりこれを使わないようにするのが筋です。ようするに、呼び出さられる関数は必要な処理をしたら即座にメインループに処理を戻し、画面の更新がメインループで行なわれるようにするべきです。
では、質問の内容のような、時間のかかる処理をする場合どうするのかというと、その通信そ処理を別スレッド/別プロセスとして動かし、メインループの中でそれらから情報を取得し画面を更新するようにします。

投稿2025/03/27 02:38

編集2025/03/27 02:52
TakaiY

総合スコア14199

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

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

nonchan1

2025/03/27 04:19

突っ込みどころ満載ですが動作確認できました。 どうしたらよいかわからず、あれもこれも加えプログラムです。笑 CAN通信のアダプターを介して測定器との通信を行うので簡略化することができました、 お忙しい中、丁寧な回答本当にありがとうございました。
nonchan1

2025/03/27 04:19

回答ありがとうございます。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。
guest

0

シリアル通信時tkinterでの表示

とのことですが、

recv4 = ser.read(13)

で、recv4に受信データが入ります。
これを表示させてるのはどこでしょうか

投稿2025/03/27 01:46

y_waiwai

総合スコア88159

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

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

nonchan1

2025/03/27 01:57

コメントありがとうございます。 recv4 = ser.read(13)だけでは表示されません。 print("FC1_STATE ",STATE[k])を加えると、terminalで表示されます
y_waiwai

2025/03/27 03:28

ってことは、提示のコードでは表示はしていないってことでしょうか?
y_waiwai

2025/03/27 12:06 編集

ああそうか。表示させるコード書いてください、という質問でしたか。そりゃ勘違いしてましたわ。。 てっきり、表示させてるつもりだけどされていない、という質問かと思ってましたw
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.32%

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

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

質問する

関連した質問