Pranav HS
Pranav HS

Reputation: 63

Not able to update text in tkinter python

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

Answers (1)

TheLizzard
TheLizzard

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.StringVars 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

Related Questions