Home > Software engineering >  How works after() and multiprocessing using tkinter
How works after() and multiprocessing using tkinter

Time:04-01

I wondering how works after() and multiprocessing while using tkinter. Here is a pseudo example

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()

Now I have a few questions. When I run the program like this, the GUI does not freeze and I get my "print" output. Now I don't want to get a print output but I want to communicate with the GUI and update the label without the GUI freezing. Now I heard about the after() method, but I also read that this method doesn't call a new thread but delays the blocking of the GUI. If I have understood this correctly. Furthermore, I also read that tkinter is generally a single thread. Is there nevertheless a possibility to decouple the IO tasks from the GUI? For this, I would have to use the task outside of the mainloop()?

in this entry Tkinter understanding mainloop there is an example of the after() method, but I could not derive an application for me. Here is another link that deals with the topic but could not help me specifically.

CodePudding user response:

With respect to https://stackoverflow.com/a/47920128/15959848 I solved my problem.

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)

  • Related