after() 和使用 tkinter 的多重处理如何工作
How works after() and multiprocessing using tkinter
我想知道 after()
和 multiprocessing
在使用 tkinter 时是如何工作的。这是一个伪例子
import asyncio
import tkinter as tk
import multiprocessing as mp
class pseudo_example():
def app(self):
self.root = tk.Tk()
self.root.minsize(100,100)
# multiprocessing
start_button = tk.Button(self.root, text="start", command=lambda: mp.Process(target=self.create_await_fun).start())
# regular call
#start_button = tk.Button(self.root, text="start", command = self.create_await_fun())+
start_button.pack()
self.testfield = tk.Label(self.root, text="test")
self.testfield.pack()
self.root.mainloop()
def create_await_fun(self):
asyncio.run(self.await_fun())
async def await_fun(self):
# cross communication between two threads doesn't work jet
#self.testfield["text"] = "start waiting"
#self.root.update_idletasks()
print("start waiting")
await asyncio.sleep(10)
print("end waiting")
#self.testfield["text"] = "end waiting"
#self.root.update_idletasks()
if __name__ == '__main__':
gui = pseudo_example()
gui.app()
现在我有几个问题。当我 运行 这样的程序时,GUI 不会冻结,我得到“打印”输出。现在我不想获得打印输出,但我想与 GUI 通信并在 GUI 不冻结的情况下更新标签。现在我听说了 after()
方法,但我也读到这个方法不调用新线程但延迟了 GUI 的阻塞。如果我理解正确的话。此外,我还读到 tkinter 通常是单线程。尽管如此,是否有可能将 IO 任务与 GUI 分离?为此,我必须在 mainloop() 之外使用任务?
在这篇文章中 there is an example of the after()
method, but I could not derive an application for me. Here is another link 涉及主题但不能具体帮助我。
关于我解决了我的问题。
class pseudo_example():
def app(self,async_loop):
self.root = tk.Tk()
self.root.minsize(100,100)
self.start_button = tk.Button(self.root, text="start", command=lambda: self.create_await_fun(async_loop))
self.start_button.pack()
self.testfield = tk.Label(self.root, text="output")
self.testfield.pack()
self.root.mainloop()
def create_await_fun(self,async_loop):
threading.Thread(target=self.asyncio_thread, args=(async_loop,)).start()
self.start_button["relief"] = "sunken"
self.start_button["state"] = "disabled"
def asyncio_thread(self, async_loop):
async_loop.run_until_complete(self.await_fun())
async def await_fun(self):
self.testfield["text"] = "start waiting"
self.root.update_idletasks()
await asyncio.sleep(2)
self.testfield["text"] = "end waiting"
self.root.update_idletasks()
await asyncio.sleep(1)
self.testfield["text"] = "output"
self.root.update_idletasks()
self.start_button["relief"] = "raised"
self.start_button["state"] = "normal"
if __name__ == '__main__':
gui = pseudo_example()
async_loop = asyncio.get_event_loop()
gui.app(async_loop)
我想知道 after()
和 multiprocessing
在使用 tkinter 时是如何工作的。这是一个伪例子
import asyncio
import tkinter as tk
import multiprocessing as mp
class pseudo_example():
def app(self):
self.root = tk.Tk()
self.root.minsize(100,100)
# multiprocessing
start_button = tk.Button(self.root, text="start", command=lambda: mp.Process(target=self.create_await_fun).start())
# regular call
#start_button = tk.Button(self.root, text="start", command = self.create_await_fun())+
start_button.pack()
self.testfield = tk.Label(self.root, text="test")
self.testfield.pack()
self.root.mainloop()
def create_await_fun(self):
asyncio.run(self.await_fun())
async def await_fun(self):
# cross communication between two threads doesn't work jet
#self.testfield["text"] = "start waiting"
#self.root.update_idletasks()
print("start waiting")
await asyncio.sleep(10)
print("end waiting")
#self.testfield["text"] = "end waiting"
#self.root.update_idletasks()
if __name__ == '__main__':
gui = pseudo_example()
gui.app()
现在我有几个问题。当我 运行 这样的程序时,GUI 不会冻结,我得到“打印”输出。现在我不想获得打印输出,但我想与 GUI 通信并在 GUI 不冻结的情况下更新标签。现在我听说了 after()
方法,但我也读到这个方法不调用新线程但延迟了 GUI 的阻塞。如果我理解正确的话。此外,我还读到 tkinter 通常是单线程。尽管如此,是否有可能将 IO 任务与 GUI 分离?为此,我必须在 mainloop() 之外使用任务?
在这篇文章中 after()
method, but I could not derive an application for me. Here is another link 涉及主题但不能具体帮助我。
关于
class pseudo_example():
def app(self,async_loop):
self.root = tk.Tk()
self.root.minsize(100,100)
self.start_button = tk.Button(self.root, text="start", command=lambda: self.create_await_fun(async_loop))
self.start_button.pack()
self.testfield = tk.Label(self.root, text="output")
self.testfield.pack()
self.root.mainloop()
def create_await_fun(self,async_loop):
threading.Thread(target=self.asyncio_thread, args=(async_loop,)).start()
self.start_button["relief"] = "sunken"
self.start_button["state"] = "disabled"
def asyncio_thread(self, async_loop):
async_loop.run_until_complete(self.await_fun())
async def await_fun(self):
self.testfield["text"] = "start waiting"
self.root.update_idletasks()
await asyncio.sleep(2)
self.testfield["text"] = "end waiting"
self.root.update_idletasks()
await asyncio.sleep(1)
self.testfield["text"] = "output"
self.root.update_idletasks()
self.start_button["relief"] = "raised"
self.start_button["state"] = "normal"
if __name__ == '__main__':
gui = pseudo_example()
async_loop = asyncio.get_event_loop()
gui.app(async_loop)