I want to create a non blocking gui with tkinter. The way I have seen it so far, you can do as with a mutliprocess. But now I have the problem that I want to access the mainloop of the gui again with the newly created thread and I always get an error here. can you jump back and forth between two threads or is there another method to not block the gui?
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)
start_button = tk.Button(self.root, text="start", command=lambda: mp.Process(target=self.create_await_fun).start())
start_button.pack() #
self.testfield = tk.Label(self.root, text="test")
self.testfield.pack()
#self.root.update_idletasks()
self.root.mainloop()
def create_await_fun(self):
asyncio.run(self.await_fun())
async def await_fun(self):
self.root.update_idletasks()
self.testfield["text"] = "start waiting"
await asyncio.sleep(2)
self.testfield["text"] = "end waiting"
if __name__ == '__main__':
try:
gui = pseudo_example()
gui.app()
except KeyboardInterrupt:
print("Interrupted")
sys.exit()
Error message:
[xcb] Unknown sequence number while processing queue [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called [xcb] Aborting, sorry about that. XIO: fatal IO error 0 (Success) on X server ":0" after 401 requests (401 known processed) with 0 events remaining. python3.8: ../../src/xcb_io.c:259: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
i know that the after() method exists but i don't know how to use it with asyncio without starting the asyncio task. Asyncio is unnecessary in the minimal example but I need it for another application.
CodePudding user response:
Tkinter doesn't support multi-task/multithreading. You could use mtTkinter which provides thread safety when using multi-tasking: