Reputation: 63
whenever I click the restart button to update the text of notification1 (label)
from tkinter import *
import tkinter as tk
from multiprocessing import Process
def notify(text):
notify_heading_text.set(f"App : {text}")
def on_restart():
notify("This text will be updated")
t1 = Process(target=print_hi)
t1.daemon = True
t1.start()
def print_hi():
notify("Hi There")
if __name__ == '__main__':
root = Tk()
root.geometry('400x400')
root.resizable(0, 0)
global notify_heading_text
notify_heading_text = tk.StringVar()
notification1 = Label(height=1, textvariable=notify_heading_text, bd=0)
notification1.pack(fill=X, side=TOP)
notification1.configure(bg='white', fg='black', font=('Helvetica', 12, 'bold'), pady=10)
bind3 = tk.StringVar()
b3 = Button(root, borderwidth=0, fg="white", activebackground='#40556a', activeforeground='white', bg="black",
textvariable=bind3, command=on_restart, font=('Helvetica', 12, 'bold'), padx=10, pady=6)
bind3.set('Restart')
b3.pack(side=RIGHT)
root.mainloop()
I get this error
Process Process-1:
Traceback (most recent call last):
File "C:\Users\prana\AppData\Local\Programs\Python\Python39\lib\multiprocessing\process.py", line 315, in _bootstrap
self.run()
File "C:\Users\prana\AppData\Local\Programs\Python\Python39\lib\multiprocessing\process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\prana\PycharmProjects\tkinter\main.py", line 18, in print_hi
notify("Hi There")
File "C:\Users\prana\PycharmProjects\tkinter\main.py", line 7, in notify
notify_heading_text.set(f"App : {text}")
NameError: name 'notify_heading_text' is not defined
notify("This text will be updated")
inside on_restart() method works fine and updates text but that same method inside print_hi() method does not update the text of Tkinter window
says 'notify_heading_text' is not defined although it is declared as a global variable. For some reason, I can't use root.after()
which updates the display of the Tkinter window without errors and works fine but I want to thread.
Upvotes: 0
Views: 173
Reputation: 7680
Try this:
import tkinter as tk
from threading import Thread
def notify(text):
label.config(text=f"App : {text}")
def on_restart():
notify("This text will be updated")
t1 = Thread(target=print_hi, daemon=True)
t1.start()
def print_hi():
notify("Hi There")
root = tk.Tk()
label = tk.Label(root, text="")
label.pack(fill="x", side="top")
button = tk.Button(root, text="Restart", command=on_restart)
button.pack()
root.mainloop()
The problem with your code is that you are using multiprocessing
and that creates a new python process with its own memory. The new python process can't find the global notify_heading_text
variable so it throws the error. I switched multiprocessing
to threading
and it should now work. Different threads inside a process use the same memory so that is why the error no longer appears.
Also just to simplify the code I replaced the tk.StringVar
s and used <tkinter.Label>.config(text=<new text>)
Edit:
The reason I couldn't see the error message in IDLE, is because the error is written to the console but in the IDLE case it runs without a console. Therefore the error was still there but there was no way of seeing it. Also reading this proves that multiprocessing
can't find the global variable that you are referencing. That is why I use threading
most of the time.
Upvotes: 1