【Python】TkinterとPyserialとMulti Thread 。。 いい具合にやってくれる?【GUI+並列】

ちょっとだけGUIを書こうと。。

【Python】GUI用のTkinterのメモTips集 pygubuかも【リンク集】

COMポートを読んで来て、表示させるだけなんですが。。 表示とCOM取得を同時に並列で動かさないと。。コマンドラインにprintするだけなら。。だーっと表示できるものが、GUIだと。。それぞれマルチスレッドで動かさないとだめなんですね(笑)当たり前だけど。。

import threading

って入っているコードがあって。。やっと気づいた(笑)

でも。。

import concurrent.futures

というのもあって。。どっちなのかな?と。。

Threading

https://docs.python.org/ja/3/library/threading.html

こちらは、Threadingを使う方法。。stackoverflowで見つけた回答を動くように改変。コムポートなどの設定と、ser.writeやreadでUTF-8 を asciiと変えてます。

https://stackoverflow.com/questions/65887942/button-problem-in-multi-threading-python-tkinter-serial-monitor

コード自体 赤字のところが threadingに関係するところ

import threading
from tkinter import *
import tkinter as tk
import serial
root = tk.Tk()
COM = "COM4"
ser = serial.Serial(port=COM, baudrate=57600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, timeout=2)
ser.isOpen()
msg = ""


# read Serial
def ReadSerial():
 global msg
 msg = ""
 msg = ser.readline()[:-2].decode("ascii")
 if msg != "":
 print(msg)

return msg
# write Serial
def WriteSerial(sendmsg):
 print("send")
 ser.write(bytes(sendmsg, 'ascii'))
 ReadSerial()


# Tkinter
root.title("WIP NAME")
root.geometry("650x400")
inputData = Entry(root, text="<Slave1&p>") # input for enter the message to write
entrymsg = inputData.get() # get the massage
buttonMsg = Button(root, text="send", command = lambda: WriteSerial(inputData.get())) # create a send button for send the message
readData = Label(root, text=msg) # show message in Tkinter
ReadSerial()
# show items
inputData.grid()
readData.grid()
buttonMsg.grid()


# GUI thread
def TkinterGui():
 while 1==1:
 global msg
 entrymsg = inputData.get()


# Serial thread
def SerialProgram():
  global msg
 while 1==1:
 ReadSerial()
 readData["text"]=msg
 readData.update_idletasks()


x = threading.Thread(target=TkinterGui, args=())
y = threading.Thread(target=SerialProgram, args=())
x.start()
y.start()

root.mainloop()

 

どうやら・・ 関数を定義して、TkinterGuiの関数と、SerialProgramを、スレッドですよって宣言して、それらをスタートさせると、それぞれが同時に動くって感じですね。

Tkinter に作った Labelに受信した値を表示させるってことなんですが、こういう風にしないとTkinter(画面)に反映されないんですよね。。

わかりやすい。

他の例も。。

Pythonのサンプルコード

 

Concurrent.futures

どうも。。これは、非同期実行ができるようです。順番にするというより、同時に動いている感じですかね?表現方法違いかも? よくわかってないけど。。 受信と送信を別プロセスで動かす感じです。

https://docs.python.org/ja/3/library/concurrent.futures.html

コードの例は、こちらから。。

import serial
import time
import concurrent.futures

ser = serial.Serial('COM4',57600,timeout=None) 

def func1():
 while True:
 line = ser.readline()
 print(line)

def func2():
 while True:
  flag=bytes(input(),'utf-8')
  ser.write(flag)
  if(flag==bytes('a','utf-8')):
    break;
  time.sleep(1)

 ser.close()

if __name__ == "__main__":
executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
executor.submit(func1)
executor.submit(func2)

こちらも使い方は同じような感じですね。

Afterを使ってるのもある。

こんなのもありますね。

インターバルを自分自身で用意して、1秒に一回づつしか通信しないようにしてます。

なるほど。。って。。この場合、Tkinter部分のループと同時に動いているってことかな?

https://www.texio.co.jp/uploads/WebExpo/Study/Study_0001/python0001.html

並行処理と並列処理

ここに綺麗にまとまっているのがありました。

https://zenn.dev/ryo_kawamata/articles/python-concurrent-thread

https://srbrnote.work/archives/5776

thread(時分割) と Process(CPU並列) を同じような感じで使えるようにしたのが、concurrent.futures って感じですかね。

TkinterとSerialを同時に使うって、めんどくさいな(笑) どっちもループで動いているので処理の受け渡しが必要ってことですね。

昔のVB6.0とかでやってた時ってこんな処理してたっけ??(笑) ってやってたような気がする(笑) 通信しだすと、ボタン受け付けな~いって。。そういえば。。って思い出した(笑)

投稿者 tom2rd

コメントを残していただけるとありがたいです

Loading Facebook Comments ...

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください