-1

Hey guys I have to classes that both create a Frame. The first one contains a button that is supposed to close its frame. The second frame simply contains a Label. My code should first create the frame with the button and when the button is pressed the second window should show up. What happens is that when pressing the button a "merged" window is created that contains the button and the label.

import tkinter as tk

class Window1(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)
        self.grid()
        self.btn = tk.Button(self,text = "button",command = self.run)
        self.btn.grid(row = 0,column = 0)

    def run(self):
        tk.Frame.quit(self) 

class Window2(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)       
        self.grid()
        self.label = tk.Label(self,text = "label ")
        self.label.grid(row = 0,column = 0)

w = Window1()
w.mainloop()

v = Window2()
v.mainloop()

button images

The first picture is before you press the button, the next one after you pressed the button. The problem seems that tk.Frame.quit(self) doesn't work correctly. I tried similar ways to close the window such as:

tk.Frame.destroy(self)

but that doesn't help either.

edit: I solved it by inheriting the class from tk.TK instead of tk.Frame

Luca9984
  • 141
  • 6
  • 4
    create `root = tk.Tk()`. `Frame` doesn't create window - it only group elements. `Tk()` creates window. If you want to close window then you need `root.destroy()`. If widget doesn't have parent then it uses `root` - `Frame ` does it too. if you doesn't create `root` then it will create root somewhere in code but you have no access to `root` to close it – furas Dec 14 '17 at 10:14
  • BTW: to close frame use `self.destroy()` (but it will not close window). If you use Python 3 then you can use `super().__init__()` instead of `tk.Frame.__init__(self)` – furas Dec 14 '17 at 10:29
  • @furas and in Python2 as well only slightly less convenient with `super( MyClassName, self ).__init__()` – mikuszefski Dec 14 '17 at 10:45
  • @mikuszefski I know it but main idea in my comment was that with `super()` in Pyhton 3 you don't have to use class name but in Python 2 you still need to use class name so you can keep old method :) – furas Dec 14 '17 at 10:52
  • @furas *...so you can keep old method...* Well not really as this behaves differently if you change [inheritance](https://stackoverflow.com/a/222922/803359). – mikuszefski Dec 14 '17 at 11:51
  • @mikuszefski but OP doesn't change inheritance in this example. – furas Dec 14 '17 at 13:32
  • @furas We shouldn't discuss this in detail here. I agree with your info that `super` could/should be used. I only added that this is not limited Python3 and there are good reasons to use it in Python2 as well. Whether or not the minimal example of the OP contains inheritance does not change the point. No offence. Cheers. – mikuszefski Dec 14 '17 at 13:41
  • @furas Isn't your very first comment instead an answer? – Nae Dec 15 '17 at 09:12
  • @Nae seem you are right - I created answer. – furas Dec 15 '17 at 17:54

1 Answers1

2

Frame doesn't create window - it only group elements. Tk() creates window.

To close window you have to destroy() object create by Tk(). But you don't creat it manually root = tk.Tk() so tkinter create it automatically, but you have no access to this root to close it.

If widget doesn't have parent then it uses root and your Frame does it too.

import tkinter as tk

class Window1(tk.Frame):

    def __init__(self, master):
        # send `root` to `Frame` as its parent
        tk.Frame.__init__(self, master) 
        # `Frame` will keep `master as `self.master` 
        # so we don't have to do `self.master = master` manually

        self.grid()
        self.btn = tk.Button(self, text="Hello Button", command=self.run)
        self.btn.grid(row=0, column=0)

    def run(self):
        # use `master` (`root`) to destroy  it
        self.master.destroy() 

class Window2(tk.Frame):

    def __init__(self, master):
        tk.Frame.__init__(self, master)       
        self.grid()
        self.label = tk.Label(self, text="Hello Label")
        self.label.grid(row=0, column=0)

root = tk.Tk()  # create main window as `root`
Window1(root)   # send `root` to `Window1` and later to `Frame`
root.mainloop()

root = tk.Tk()
Window2(root)
root.mainloop()
furas
  • 134,197
  • 12
  • 106
  • 148