Summary: In Python when I update a Tkinter label text from a spawned process, the label on the GUI is not updated, although the spawned process is executed. How can I make it update from the spawned process?
Im am working with Python 2.7.2 in Lubuntu 20.04
EDIT: I also tried with Python 3.8, had to install python3-tk extra, change a little syntax (parentheses after print command and replacing Tkinter with tkinter), but problem still there looking identical. END EDIT
Here is my sample code working standalone to try out:
from Tkinter import *
from multiprocessing import Process
# simple Label change invoked from "simple" button
def bnAction_sync():
print "bnAction_sync"
changeLabel()
print "bnAction_sync done"
# asynchronous label change invoked from Async button
def bnAction_async():
print "bnAction_async"
p = Process(target=changeLabel)
p.start()
print "bnAction_Async done"
def changeLabel():
print "change label"
lbl['text'] = "Text changed"
### Apr 19 2021:
### uncommenting the following line really updates label but makes program crash ###
# root.update_idletasks
print "change label done"
root = Tk()
btnSync = Button(root, text="simple", command=bnAction_sync)
btnSync.pack()
btnAsync = Button(root, text="async", command=bnAction_async)
btnAsync.pack()
lbl = Label(root, text="Initial text")
lbl.pack()
root.mainloop()
If I press the "simple" button, text is updated in label. All good.
But: If I press "async" button,
- as you can verify by the prints I have provided, the asynchronous process starts,
- the label text updation line is executed.
- But: Here is my problem: The label on the GUI is not displaying the updated text.
The reason I want to do it this way: Because I am starting a long running spawned process, after which I want to update the label. All other processes however should run in parallel. So I created a function f, containing the long running function and the label update function sequentially. I want to call f asynchronously. So in principle:
def longprocess():
code...
def updatelabel_after_longprocess():
code...
def f():
longprocess()
updatelabel_after_longprocess()
p = Process(target=f)
p.start()
do other things immediately
Somewhere I read, that refresh is suspended, while a script is still running. I tried some p.join inserts with no luck.
Please help, thanks!