Bugsy Coder
Bugsy Coder

Reputation: 3

Trying to change the color of a tkinter label based solely on the value of a variable

I know how to change a label's color with a command attached to a button, but I want to do it programmatically, based on a variable's value.

If an error message is sent to the build_window function, I want to display the error message on a label with a red background, and if a non-error message is sent, no message is to be displayed and no color changes are expected.

In my code, I call the function to build a tkinter window two times. The first time, I pass it a non-error message, the second time, an error message.

My code works for displaying the error message when expected, the problem is only with changing the background color of the error message label.

If I un-comment the l1.config(bg="red") command shown, I get this error when passing an error message to build_window():

UnboundLocalError: local variable 'l1' referenced before assignment

on the l1.config(bg="red") command.

If I move the entire if structure to just before mainloop(), I get this error even when passing the non-error message:

UnboundLocalError: local variable 'error_message' referenced before assignment

on the l1=Label(root,text = error_message) command.

If I add global l1 and global error_message to build_window(), the error I get is this:

tkinter.TclError: invalid command name ".!label"

I also tried just initially defining the label with bg="red", hoping that when I send a zero-length string, it would still be gray, but it displays a bit of red in the middle of the l1 label.

I've been writing simple python for a while, but I'm new to GUI apps and tkinter just confuses me every time I try something.

I've searched for a solution but could not find anything addressing changing a window without using a command attached to a button.

Any advice or clarification would be greatly appreciated!

from tkinter import Tk, IntVar, Label, mainloop, Button

def build_window(incoming_error_message) :

    if incoming_error_message == "initial value" :
        error_message = ""
    else :
        #l1.config(bg="red")
        error_message = incoming_error_message
    
    def quitHandler():
        root.destroy()

    root = Tk()

    l1=Label(root,text = error_message)
    l1.grid(row=0,column=0)

    quitButton = Button(root, text="To end, click here",command=quitHandler)
    quitButton.grid(row=1,column=0)
    
    mainloop()

def call_build_window() :
    
    build_window("initial value")
    build_window("Error!")
        
call_build_window()

Upvotes: 0

Views: 1439

Answers (1)

Wolf
Wolf

Reputation: 10238

One option is to place the label creation within the condition and reorder the surrounding code a little bit. I also replaced grid by pack and skipped keeping names for variables which are actually constants, all that changes were made to keep the code small:

from tkinter import Tk, Label, mainloop, Button

def build_window(error_message):
   
    root = Tk()
    
    if error_message == "initial value":
        Label(root, text="").pack()
    else:
        Label(root, text=error_message, bg="red").pack()
            
    def quitHandler():
        root.destroy()

    Button(root, text="To end, click here", command=quitHandler).pack()
    
    mainloop()

def call_build_window():
    
    build_window("initial value")
    build_window("Error!")
        
call_build_window()

This of course is a small case study and shouldn't be used to build on it. I think it should be reworked so that there is a maybe function that takes the indicator if the message is as a second argument with the text always being displayed. All that would be much easier in a more object-oriented approach. (Also remember that Tk() is normally called only once and secondary top-level windows are created via Toplevel(), see Python - Tkinter - invisible text in ttk.Entry in sub window or tkinter: Open a new window with a button prompt. )

By using tkinter.ttk it's also possible to change the widget's style at runtime, see the answer to Changing ttk widget text color for an example.

Upvotes: 1

Related Questions