0

I am building a GUI with Tkinter in which I would like to give users the option of changing an entry widget to a label widget (and vice-versa) by clicking a button.

I have tried a few different approaches but can't get it to work. Here is one of the ways I've tried to approach this problem:

import tkinter as tk

show_label = False


class App(tk.Tk):

    def __init__(self):
        super().__init__()
        label = tk.Label(self, text="This is a label")
        entry = tk.Entry(self)
        button = tk.Button(self, text="Label/Entry",
                           command=self.change)
        if show_label:
            label.pack()
        else:
            entry.pack()

        button.pack()

    def change(self):
        global show_label
        show_label = not show_label
        self.update()

if __name__ == '__main__':
    app = App()
    app.mainloop()

Aside from the above, I have also tried:

  • Updating the instance of app inside the mainloop, i.e. after instantiating app = App()
  • Making show_label a class variable and the change() a class method

Any help on the matter is greatly appreciated!

Thanks

jda5
  • 1,390
  • 5
  • 17
  • The `__init__` function is only called once on your app. The set of widgets in the window are changeable but you'll have to do this elsewhere. See also https://stackoverflow.com/q/3819354/1256452 – torek Jun 01 '20 at 12:23

1 Answers1

2

It appears that the mistake you're making is thinking that the code in __init__ runs more than once. It only runs once when you create an instance of App.

To fix your code, move the logic for displaying the entry or label into the code that runs when you click the button. Also, you need to use instance variables to hold references to the widgets so that you can refer to them in other functions.

import tkinter as tk

class App(tk.Tk):

    def __init__(self):
        super().__init__()
        self.label = tk.Label(self, text="This is a label")
        self.entry = tk.Entry(self)
        self.button = tk.Button(self, text="Label/Entry",
                                command=self.change)
        self.button.pack()
        self.show_label = False

    def change(self):
        self.show_label = not self.show_label

        if self.show_label:
            self.entry.pack_forget()
            self.label.pack()
        else:
            self.label.pack_forget()
            self.entry.pack()


if __name__ == '__main__':
    app = App()
    app.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685