我正在嘗試了解面向物件的 python 并使用 tkinter 和執行緒。我在網上閱讀了大量 SO 問題和其他各種資源。我已經能夠解決大部分問題,但是我對如何從另一個執行緒更新 Treeview 專案有點迷茫。我一直無法找到以我能理解的方式說明這一點的東西。
我讀過 tkinter 必須在主執行緒中運行,并且您不能從另一個執行緒更新它,因此我需要使用佇列將內容傳遞給它。
下面的代碼有效,盡管它可能不是最好的做事方式。絕對歡迎任何改進,但我發布的主要內容是 Treeview 問題。
在我看到的例子中,人們通常只是使用亂數生成器或其他東西通過佇列傳遞整數來演示一些簡單的事情。我理解這一點,但是如何使用佇列傳遞和運行實際命令或以其他方式更新位于主執行緒中的 Treeview 專案?
如果不是在另一個執行緒中,我會使用類似的東西:
tv_files.item('File1', values=('tst1', 'tst2'))
import tkinter as tk
from tkinter import ttk
from threading import Thread
from queue import Queue
import time
class TkThread:
def __init__(self):
self.tk = tk.Tk()
self.message_queue = Queue()
self.message_event = '<<message>>'
self.tk.bind(self.message_event, self.process_message_queue)
def run_tk(self):
self.tk.title('My Window')
self.tv_files = ttk.Treeview(
self.tk,
columns=('Filename', 'Status'),
show='headings')
self.tv_files.pack(
side='top',
padx=10,
pady=10)
# Set up columns
self.tv_files.heading('#1', anchor='w', text='Filename')
self.tv_files.column('#1', anchor='w', width=150)
self.tv_files.heading('#2', anchor='w', text='Status')
self.tv_files.column('#2', anchor='w', width=150)
self.tv_files.insert('', 'end', id='File1', values=('File1', 'Status1'))
self.btn_run = ttk.Button(
self.tk,
text= 'Run',
compound='top',
command = run_thread)
self.btn_run.pack(
side='top',
padx=10,
pady=10)
self.tk.lift(); self.tk.mainloop()
def send_message_to_ui(self, message):
self.message_queue.put(message)
self.tk.event_generate(self.message_event, when='tail')
def process_message_queue(self, event):
while self.message_queue.empty() is False:
message = self.message_queue.get(block=False)
# process the message here
print(message)
def work():
time.sleep(3)
tk_thread.send_message_to_ui('Test Message')
def run_thread():
thread = Thread(target=work)
thread.start()
if __name__ == '__main__':
tk_thread = TkThread()
tk_thread.run_tk()
uj5u.com熱心網友回復:
你似乎掌握了基礎知識。只需將專案添加到您可以解壓縮并插入到樹中的佇列中。
例如,您可以將字典添加到佇列中:
def work():
time.sleep(3)
message = {
"id": "File1",
"values": ('tst1', 'tst2')
}
tk_thread.send_message_to_ui(message)
在事件處理程式中,您可以從訊息中提取資料并將其插入到樹中:
def process_message_queue(self, event):
while self.message_queue.empty() is False:
message = self.message_queue.get(block=False)
self.tv_files.insert(message['id'], "end", values=message['values'])
如果你想變得更花哨,你可以傳遞函式的名稱、args 和 kwargs,這樣你的執行緒就可以在 GUI 中做任何事情:
發送訊息:
def work():
time.sleep(3)
message = {
"attr": "tv_files",
"method": "insert",
"args": ("File1", "end"),
"kwargs": {
"values": ['tst1', 'tst2']
},
}
tk_thread.send_message_to_ui(message)
處理訊息:
def process_message_queue(self, event):
while self.message_queue.empty() is False:
message = self.message_queue.get(block=False)
attr = getattr(self, message['attr'])
method = getattr(attr, message['method'])
method(*message['args'], **message['kwargs'])
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/398949.html
標籤:Python 特金特 python-多线程
上一篇:y'=y^2 1的數值解題
