Search code examples
pythonmultithreadingtkinterglobal-variables

Global Variable not working with Threads - Python


I want to be able to change the background colour of a Tkinter frame in a thread, the frame is declared in a separate function. I receive the following error when I run the following code.

Error: NameError: name 'mainScreen' is not defined

Code:

import tkinter as tk
from tkinter import ttk
from multiprocessing import Process


def main():
    global mainScreen
    
    root = tk.Tk()
    root.geometry('1040x540+50+50')

    mainScreen = tk.Frame(root, width = 1040, height = 540)
    mainScreen.place(x=0, y=0)

    root.mainloop()


def test(): # This function is in a thread as it will be run as a loop.
    while True:
        mainScreen.configure(bg='red')

if __name__ == '__main__':
    p2 = Process(target = test)
    p2.start()
    main()

Any help is appreciated.


Solution

  • You can replace your whole code with this:

    import tkinter as tk
    
    def main():
        global mainScreen
    
        root = tk.Tk()
        root.geometry('1040x540+50+50')
    
        mainScreen = tk.Frame(root, width=1040, height=540)
        mainScreen.place(x=0, y=0)
        mainScreen.configure(bg='red')
        root.mainloop()
    
    
    if __name__ == '__main__':
        main()
    
    

    And if you want to change colours you can do something like this:

    import time
    import tkinter as tk
    from threading import Thread
    
    
    def test(mainScreen):  # This function is in a thread as it will be run as a loop.
        while True:
            try:
                time.sleep(1)
                mainScreen.configure(bg='red')
                time.sleep(1)
                mainScreen.configure(bg='blue')
            except RuntimeError:
                break
    
    
    if __name__ == '__main__':
        root = tk.Tk()
        root.geometry('1040x540+50+50')
    
        mainScreen = tk.Frame(root, width=1040, height=540)
        mainScreen.place(x=0, y=0)
        p2 = Thread(target=test, args=(mainScreen,))
        p2.start()
    
        root.mainloop()