1

I have three labels that are directly under eachother (see image). I'd like the labels to be collapsed when they're empty.

In the case of the image, the second label is empty. I'd like the third label to be placed on the location of the second label.

In WPF (.NET) this would be done via:

<Style TargetType="TextBlock">
        <Style.Triggers>
            <Trigger Property="Text" Value="">
                <Setter Property="Visibility" Value="Collapsed" />
            </Trigger>
        </Style.Triggers>
</Style>

The simplified code of the picture below is as such:

import customtkinter as ctk

gui = ctk.CTk()

status = ctk.StringVar(value="status_test")
warning = ctk.StringVar(value="")
error = ctk.StringVar(value="error_test")

ctk.CTkLabel(gui, textvariable=status, text_color="grey", wraplength=gui.winfo_vrootwidth()).pack()
ctk.CTkLabel(gui, textvariable=warning, text_color="yellow", wraplength=gui.winfo_vrootwidth()).pack()
ctk.CTkLabel(gui, textvariable=error, text_color="red", wraplength=gui.winfo_vrootwidth()).pack()

gui.mainloop()

Image of UI

1
  • make sure you dont set visibility of the control anywhere else Commented Sep 10, 2024 at 11:21

1 Answer 1

1

The normal way to do this is to is to call pack_forget when the label is empty, given that you're using pack.

This requires that you separate the creation of the labels from the layout of the labels so that you can reference them individually.

Here's an example:

import customtkinter as ctk

gui = ctk.CTk()

status = ctk.StringVar(value="status_test")
warning = ctk.StringVar(value="warning_test")
error = ctk.StringVar(value="error_test")

status_label = ctk.CTkLabel(gui, textvariable=status, text_color="grey", wraplength=gui.winfo_vrootwidth())
warning_label = ctk.CTkLabel(gui, textvariable=warning, text_color="yellow", wraplength=gui.winfo_vrootwidth())
error_label = ctk.CTkLabel(gui, textvariable=error, text_color="red", wraplength=gui.winfo_vrootwidth())

status_label.pack()
warning_label.pack()
error_label.pack()


def add_warning(message):
    if message == "":
        warning_label.pack_forget()
    else:
        warning_label.pack(after=status_label)
        warning.set(message)

b1 = ctk.CTkButton(gui, text="Add warning", command=lambda: add_warning("Warning!"))
b2 = ctk.CTkButton(gui, text="Remove warning", command=lambda: add_warning(""))
b1.pack(side="bottom")
b2.pack(side="bottom")

gui.mainloop()
Sign up to request clarification or add additional context in comments.

3 Comments

Would it also be possible to add this feature to the label itself, by for instance inheriting from it. I assume the Label gives some sort of callback function to the textvariable to update itself. Would it be possible to amend this callback function?
@Ulas: you can add a trace on the variable which can call a function whenever the variable changes.
That would work. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.