Search code examples
pythontkinternew-windowcreatewindow

python 3.8 tkinter calling new window from method creates a blank window


I am trying to call a new window by pushing the button of an existing window. The original window should close when the new window is being created. When I push the button the new window will show up as expected but additionally a blank window will appear. Using tk.Tk() or tk.Toplevel() will lead to the same result.

Later in the program I want to destroy the created window again. When using tk.Tk() closing the blank window by mouse will create an error "application has been destroyed" when the destroy() method gets applicated to the new window.

import tkinter as tk
from tkinter import messagebox


def main():

    root = tk.Tk()
    root.title("Hauptmenü")

    Menue = MainMenue(root)
    Menue.pack()

    root.mainloop()


class MainMenue(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        self.button_rennen = tk.Button(self, text="New Window", width=20, command=self.call_bet)
        self.button_rennen.pack()

    def call_bet(self):
        self.destroy()
        root2 = tk.Tk()
        Bet = BetFrame(root2)
        Bet.pack()



class BetFrame(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        self.button = tk.Button(text="Wette platzieren",
                           command=self.question)

        self.button.pack()


    def question(self):
        dialog = tk.messagebox.askokcancel(message="Destroy Window?")

        if dialog is True:
            self.destroy()


main()

I am creating a new class for every new window since the original program should return some variables. I know that there are already many questions to this topic but for me none of these seemed quite to fit and helped to find the solution for my problem. I am grateful for any help!


Solution

  • Look at this:

    import tkinter as tk
    from tkinter import messagebox
    
    
    class MainMenue(tk.Frame):
        def __init__(self, parent):
            super().__init__(parent)
    
            self.button_rennen = tk.Button(self, text="New Window", width=20,
                                           command=self.call_bet)
            self.button_rennen.pack()
    
        def call_bet(self):
            # `self.master` is the window
            Bet = BetFrame(self.master)
            Bet.pack()
            self.destroy()
    
    
    class BetFrame(tk.Frame):
        def __init__(self, parent):
            super().__init__(parent)
    
            # You need to tell the button that its master should be this BetFrame
            # If you don't it will assume you mean the window so
            # `self.destroy()` isn't going to destroy the button.
            self.button = tk.Button(self, text="Wette platzieren", command=self.question)
            self.button.pack()
    
        def question(self):
            dialog = tk.messagebox.askokcancel(message="Destroy Window?")
    
            if dialog is True:
                self.destroy()
    
    def main():
        root = tk.Tk()
    
        Menue = MainMenue(root)
        Menue.pack()
    
        root.mainloop()
    
    
    main()
    

    Your code is great but it was 2 mistakes:

    • Instead of creating a new window is it better to reuse the old one.
    • When you create your button in your BetFrame class, you don't pass anything for the master argument (the first argument). That is why the button isn't destroyed when you destroy the BetFrame object using self.destroy()