PythonでGUIを別スレッドから更新する方法について説明します。この記事では、TkinterとAsyncioを使用して、一つのスレッドでTkinterのメインループを実行し、別のスレッドでAsyncioループを実行する例を示します。
まず、以下のコードを見てみましょう。
from tkinter import *
import asyncio
import threading
import random
class AsyncioThread(threading.Thread):
def __init__(self, asyncio_loop, theWindow):
self.asyncio_loop = asyncio_loop
self.theWindow = theWindow
self.maxData = len(theWindow.varData)
threading.Thread.__init__(self)
def run(self):
self.asyncio_loop.run_until_complete(self.do_data())
async def do_data(self):
tasks = [self.create_dummy_data(number) for number in range(self.maxData)]
completed, pending = await asyncio.wait(tasks)
results = [task.result() for task in completed]
print('\\n'.join(results))
async def create_dummy_data(self, number):
sec = random.randint(1, 3)
data = '{}:{}'.format(number, random.random())
await asyncio.sleep(sec)
self.theWindow.varData[number].set(data)
print('Thread-ID: {}\\tsec: {}\\n\\t{}'.format(threading.get_ident(), sec, data))
return data
class TheWindow:
def __init__(self, maxData):
self.asyncio_loop = asyncio.get_event_loop()
self.root = Tk()
self.varData = []
for i in range(maxData):
self.varData.append(StringVar())
self.varData[i].set('<default>')
Button(master=self.root, text='Start Asyncio Tasks', command=lambda:self.do_asyncio()).pack()
for i in range(maxData):
Label(master=self.root, textvariable=self.varData[i]).pack()
Button(master=self.root, text='Freezed???', command=self.do_freezed).pack()
def do_freezed(self):
print('Tkinter is reacting. Thread-ID: {}'.format(threading.get_ident()))
def do_asyncio(self):
thread = AsyncioThread(self.asyncio_loop, self)
thread.start()
if __name__ == '__main__':
window = TheWindow(5)
window.root.mainloop()
このコードは、TkinterのGUIを別のスレッドから更新する方法を示しています。AsyncioThread
クラスは、非同期I/Oループを実行するためのスレッドを作成します。このループは、ダミーデータを作成し、それをTkinterのラベルに表示します。
この例では、AsyncioThread
クラスのdo_data
メソッドで複数のタスクを作成し、それらを非同期に実行します。各タスクは、ランダムな時間を待った後にダミーデータを作成し、それをTkinterのラベルに表示します。
このように、Pythonではスレッドと非同期I/Oを組み合わせて、GUIを別のスレッドから更新することが可能です。ただし、スレッド間でデータを共有する際には、データ競合を避けるために適切な同期メカニズムを使用することが重要です。
以上、PythonでGUIを別スレッドから更新する方法について説明しました。この情報が皆さんのPythonプログラミングに役立つことを願っています。