Shallon
Shallon

Reputation: 15

Python: calling a parent class method to deconfiey a windows (Tkinter) causes two sets of the widgets in the window

Sorry for any stupidity or ignorance on my part but I am new to Python, and coding in general. I have been trying to get a UI working for a game I'm going to make as a way of teaching myself python I have a main window and a few button widgets in this. The Play game button opens a second window (for the game itself) and hides the root window with the .withdraw method. This works perfectly. Inside the game window I have another button which I would like to destroy the game window and bring the user back to the root menu window that I have withdrawn. This seems to work except every time I call it,it creates an new, duplicate set of widgets in the window so I end up with multiple sets.

I'll post my full code at the bottom but here are what I believe are the relevant parts.

A tkinter Button calls this inside the parent class (the main window). This works fine.

def playGame(self):     #Start the main game window
    self.master.withdraw()
    gameWindow()

I'm using the bellow method inside of the child class to destroy the game window and then call a method in the parent class to bring back the earlier withdrawn window

def exitMenu(self):
    self.g.destroy()
    UI(root).showMenu()

this works except it duplicates the widgets each time resulting in this being shown:

screen capture of result

Bellow is all my code, thank you so much for any help.

import tkinter as tk
import PIL
from Config import *

root = tk.Tk()

class UI(): #Main Menu

    def __init__(self, master):

        #Create Main Menu Window

        self.master = master
        self.master.title("Monopoly")
        self.master.wm_iconbitmap('icons\Monopoly-Icon.ico')
        self.master.geometry((resolution))

        #Menu Buttons

        self.label = tk.Label(master, text= 'Welcome to Monopoly! PLACEHOLDER')
        self.playButton = tk.Button(master, text= 'Play Game', command= self.playGame)
        self.settingsButton = tk.Button(master, text= 'settings', command= self.settings)
        self.exitButton = tk.Button(master, text= 'Exit', command= self.exitGame)

        self.label.grid(columnspan=2)
        self.playButton.grid(column=0)
        self.settingsButton.grid(column=0)
        self.exitButton.grid(column=0)

    def settings(self):       #Opens Settings Window
        s = tk.Toplevel()
        s.title('Settings')
        s.wm_iconbitmap('icons\Monopoly-Icon.ico')
        s.geometry((resolution))
        self.master.withdraw()
        resLabel = tk.Label(s, text= 'Resolution')
        resOption = tk.OptionMenu(s, resolution, *resList)

        resLabel.grid(column=0,row=0)
        resOption.grid(column=0, row=4)

    def showMenu(self):     #Bring back menu windwow
        self.master.deiconify()

    def exitGame(self):    #Exit Game Method
        root.destroy()

    def playGame(self):     #Start the main game window
        self.master.withdraw()
        gameWindow()

class gameWindow(UI):

    def __init__(self):

        self.g = tk.Toplevel()
        self.g.title('Monopoly')
        self.g.wm_iconbitmap('icons\Monopoly-Icon.ico')
        self.g.geometry((resolution))

        self.menuButton = tk.Button(self.g, text= 'Main Menu', command= self.exitMenu)

        self.menuButton.grid(column=0,row=0)

    def exitMenu(self):
        self.g.destroy()
        UI(root).showMenu()

mainMenu = UI(root)

root.mainloop()

Upvotes: 0

Views: 1445

Answers (1)

Khristos
Khristos

Reputation: 983

You should pass the parent class, UI, to the child class gameWindow, then you can use the showMenu() method of the parent class in the child class.

Code for showing the main window from the child window will be: self.mainUI.showMenu() instead of UI(root).showMenu()

Child class becomes:

class gameWindow(UI):

    def __init__(self, mainUI): # Make the main window a parameter/attribute

        self.mainUI = mainUI # Make the main window a parameter/attribute
        self.g = tk.Toplevel()
        self.g.title('Monopoly')
        self.g.wm_iconbitmap('icons\Monopoly-Icon.ico')
        self.g.geometry((resolution))

        self.menuButton = tk.Button(self.g, text= 'Main Menu', command= self.exitMenu)

        self.menuButton.grid(column=0,row=0)

    def exitMenu(self):
        self.g.destroy()
        self.mainUI.showMenu()

gameWindow now requires one argument, so you pass it the main UI as self

def playGame(self):     #Start the main game window
        self.master.withdraw()
        gameWindow(self)

You can read more about hiding/showing window here

Here is the full code:

import tkinter as tk
import PIL
from Config import *

root = tk.Tk()

class UI(): #Main Menu

    def __init__(self, master):

        #Create Main Menu Window

        self.master = master
        self.master.title("Monopoly")
        self.master.wm_iconbitmap('icons\Monopoly-Icon.ico')
        self.master.geometry((resolution))

        #Menu Buttons

        self.label = tk.Label(master, text= 'Welcome to Monopoly! PLACEHOLDER')
        self.playButton = tk.Button(master, text= 'Play Game', command= self.playGame)
        self.settingsButton = tk.Button(master, text= 'settings', command= self.settings)
        self.exitButton = tk.Button(master, text= 'Exit', command= self.exitGame)

        self.label.grid(columnspan=2)
        self.playButton.grid(column=0)
        self.settingsButton.grid(column=0)
        self.exitButton.grid(column=0)

    def settings(self):       #Opens Settings Window
        s = tk.Toplevel()
        s.title('Settings')
        s.wm_iconbitmap('icons\Monopoly-Icon.ico')
        s.geometry((resolution))
        self.master.withdraw()
        resLabel = tk.Label(s, text= 'Resolution')
        resOption = tk.OptionMenu(s, resolution, *resList)

        resLabel.grid(column=0,row=0)
        resOption.grid(column=0, row=4)

    def showMenu(self):     #Bring back menu windwow
        self.master.deiconify()

    def exitGame(self):    #Exit Game Method
        root.destroy()

    def playGame(self):     #Start the main game window
        self.master.withdraw()
        gameWindow(self)

class gameWindow(UI):

    def __init__(self, mainUI): # Make the main window a parameter/attribute

        self.mainUI = mainUI # Make the main window a parameter/attribute
        self.g = tk.Toplevel()
        self.g.title('Monopoly')
        self.g.wm_iconbitmap('icons\Monopoly-Icon.ico')
        self.g.geometry((resolution))

        self.menuButton = tk.Button(self.g, text= 'Main Menu', command= self.exitMenu)

        self.menuButton.grid(column=0,row=0)

    def exitMenu(self):
        self.g.destroy()
        self.mainUI.showMenu()

mainMenu = UI(root)

root.mainloop()

Upvotes: 1

Related Questions