tkinter线程通信

时间:2017-08-13 14:29:11

标签: multithreading tkinter

我的代码应该显示tkinter小部件(注意:尚未实现)和另一个线程之间的通信。由于这两者之间的通信我选择python队列。要查看真正发生的事情,打印机会在控制台中显示,而这并不是我所期望的。

generate_text的{​​{1}}输出中的睡眠时间显示后,可以在控制台输出中看到。我期望的是,process慢于generate_text我会看到更多process然后process is called,但这种情况不会发生。

Item x

输出:

import tkinter as tk
import threading
import queue
import time

def generate_text(storage):
    count = 0
    while True:
        message = "Item {}".format(count)
        storage.put(message)
        print(message)

        count +=1

        time.sleep(3000/1000)

def process(storage):
    print("process is called")

    try:
        storage.get()
    except queue.Empty:
        print("queue empty")

    # register awake function
    root.after(500, process, message)

# init variables
message = queue.Queue()

root = tk.Tk()

t = threading.Thread(target=generate_text, args=(message,))
t.setDaemon(True)
t.start()

root.after(500, process, message)
root.mainloop()

2 个答案:

答案 0 :(得分:3)

@ Himal的答案对于当前的问题是正确的,但是您可能希望修改它以在消息生成代码中使用event_generate并让UI在事件被提升时响应事件而不是轮询像这样的队列。您可以使用root.event_generate('<<MessageQueued>>')功能中的generate_text将虚拟事件放置到Tk的事件队列中。这是线程安全的,直接调用窗口方法不是。如果还在UI代码上添加了对此虚拟事件的绑定,则Tk消息循环在接收到虚拟事件时调用绑定函数。没有更多的民意调查。

import tkinter as tk
import threading
import queue
import time

def generate_text(mainwin, storage):
    count = 0
    while True:
        message = "Item {}".format(count)
        storage.put(message)
        print("Queued {0}".format(message))
        count += 1
        mainwin.event_generate('<<MessageGenerated>>')
        time.sleep(3000/1000)

def process(storage, event):
    msg = storage.get()
    print("New message: {0}".format(msg))

def main():
    message_queue = queue.Queue()
    root = tk.Tk()
    root.bind('<<MessageGenerated>>', lambda e: process(message_queue, e))
    t = threading.Thread(target=generate_text, args=(root, message_queue,))
    t.setDaemon(True)
    t.start()
    root.mainloop()

if __name__ == '__main__':
    main()

答案 1 :(得分:2)

storage.get()是阻止功能。它不会到达root.after(500, process, message)来电,直到队列中有一个项目为止。

您可以使用storage.get_nowait()storage.get(False)来获得所需的行为。

More about Queue