2

I'm developing a program for a game in tkinter on Python, and have been trying to formulate a 'Return to Main Menu' button at the moment, but to no avail. Please could I have some help?

Here is my code so far:

from tkinter import *
from tkinter import ttk
root = Tk()

def MainMenu():
    GameButton = Button(root, text="New Game", command = NewGame)
    GameButton.pack()

    GameLabel = Label(root, text="Click to create a new 2-player game", fg="blue", font=("Helvetica",16))
    GameLabel.pack()

    HelpButton = Button(root, text="Help", command = Help)
    HelpButton.pack()

    HelpLabel = Label(root, text="Click if you would like instructions", fg="orange", font=("Helvetica",16))
    HelpLabel.pack()

    ExitButton = Button(root, text="Exit",command = exit)
    ExitButton.pack()

    ExitLabel = Label(root, text="Click to exit application", fg="red", font=("Helvetica",16))
    ExitLabel.pack()

    InstructionsLabelFunc.pack_forget()
    ReturnMenuFunc.pack_forget()

def NewGame():
    GameButton.pack_forget()
    ExitButton.pack_forget()

def Help():
    GameButton.pack_forget()
    HelpButton.pack_forget()
    ExitButton.pack_forget()

    GameLabel.pack_forget()
    HelpLabel.pack_forget()
    ExitLabel.pack_forget()

    InstructionsLabel = InstructionsLabelFunc
    InstructionsLabel.pack()

    ReturnMenu = ReturnMenuFunc
    ReturnMenu.pack()

def Exit():
    exit()

GameButton = Button(root, text="New Game", command = NewGame)
GameButton.pack()

GameLabel = Label(root, text="Click to create a new 2-player game", fg="blue", font=("Helvetica",16))
GameLabel.pack()

HelpButton = Button(root, text="Help", command = Help)
HelpButton.pack()

HelpLabel = Label(root, text="Click if you would like instructions", fg="orange", font=("Helvetica",16))
HelpLabel.pack()

ExitButton = Button(root, text="Exit",command = exit)
ExitButton.pack()

ExitLabel = Label(root, text="Click to exit application", fg="red", font=("Helvetica",16))
ExitLabel.pack()

InstructionsLabelFunc = Label(root, text="""
Taken from nrich.maths.org

This is a collection of games of skill for two players, both players have exactly the same information, chance plays no part, and each game must terminate. There is always a 'winning strategy' and all the moves can be analysed mathematically. The only advantage that either player can possibly have is to start or to play second. To work out how to win you need to start by analysing the 'end game', and the losing position to be avoided, and then work back to earlier moves. Can you find the winning strategies?

The rules are simple. Start with any number of counters in any number of piles. Two players take turns to remove any number of counters from a single pile. The winner is the player who takes the last counter.""", fg="black", font=("Calibri", 14))

ReturnMenuFunc = Button(root, text="Return to Main Menu", command = MainMenu)

InstructionsLabelFunc.pack_forget()
ReturnMenuFunc.pack_forget()

mainloop()
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • 1
    Please do _not_ delete the text of your question like that after it's been answered. Stack Overflow is a repository of questions and answers for the benefit of future readers, not just the person who asked the question. – PM 2Ring Jun 25 '16 at 15:05

2 Answers2

2

Ok, several suggestions:

1) Keep your Tkinter information in a class. This will make it much easier to keep track of later down the line when whatever it is you're making becomes more complicated.

2) Use grid() instead of pack(), it's more flexible and powerful.

3) Use root.quit() followed by sys.exit(0) to end the program instead of just exit(), it's more Pythonic and reliable.

4) You should probably define a fixed size for your window using root.geometry or some other method, and make sure the text wraps around. At the moment it doesn't.

Below is a working copy of your code, with suggestions 1-3 implemented. If you find the answer helpful, tick to accept it.

from tkinter import *
from tkinter import ttk
import sys

class GameGUI(object):

    def __init__(self, root):
        self.root = root

        self.GameButton = Button(root, text="New Game", command=self.NewGame)
        self.GameLabel = Label(root, text="Click to create a new 2-player game", fg="blue", font=("Helvetica",16))

        self.HelpButton = Button(root, text="Help", command=self.Help)
        self.HelpLabel = Label(root, text="Click if you would like instructions", fg="orange", font=("Helvetica",16))

        self.ExitButton = Button(root, text="Exit",command=self.Exit)
        self.ExitLabel = Label(root, text="Click to exit application", fg="red", font=("Helvetica",16))

        self.InstructionsLabel = Label(root, text="""
            Taken from nrich.maths.org

            This is a collection of games of skill for two players, both players have exactly the same information, chance plays no part,
            and each game must terminate. There is always a 'winning strategy' and all the moves can be analysed mathematically. The only
            advantage that either player can possibly have is to start or to play second. To work out how to win you need to start by
            analysing the 'end game', and the losing position to be avoided, and then work back to earlier moves. Can you find the winning strategies?

            The rules are simple. Start with any number of counters in any number of piles. Two players take turns to remove any number of
            counters from a single pile. The winner is the player who takes the last counter.""", fg="black", font=("Calibri", 14))

        self.ReturnMenu = Button(root, text="Return to Main Menu", command=self.MainMenu)

        self.MainMenu()

    def MainMenu(self):
        self.RemoveAll()
        self.GameButton.grid()
        self.GameLabel.grid()
        self.HelpButton.grid()
        self.HelpLabel.grid()
        self.ExitButton.grid()
        self.ExitLabel.grid()

    def NewGame(self):
        self.GameButton.grid_remove()
        self.GameLabel.grid_remove()
        self.ExitButton.grid_remove()
        self.ExitLabel.grid_remove()

    def Help(self):
        self.RemoveAll()

        self.InstructionsLabel.grid()
        self.ReturnMenu.grid()

    def RemoveAll(self):
        self.GameButton.grid_remove()
        self.GameLabel.grid_remove()
        self.HelpButton.grid_remove()
        self.HelpLabel.grid_remove()
        self.ExitButton.grid_remove()
        self.ExitLabel.grid_remove()
        self.InstructionsLabel.grid_remove()
        self.ReturnMenu.grid_remove()

    def Exit(self):
        self.root.quit
        sys.exit(0)


if __name__ == '__main__':

    root = Tk()
    GameGUI = GameGUI(root)
    root.mainloop()
heidi
  • 655
  • 6
  • 20
  • I think your advice of `grid` vs `pack` is wrong. `grid` definitely isn't "more powerful" than `pack`. It's only more powerful if you are arranging widgets in a grid. `pack` is superior when arranging things top-to-bottom or side-to-side. You should use them both, using each for their respective strengths. In fact, your code is an example of one of grid's weaknesses -- you neglect to set a weight for any rows or columns, which will give the UI bad resize behavior. This is a very common mistake people make with `grid`. – Bryan Oakley Jun 25 '16 at 16:01
0

The best solution for this type of problem is to make each "screen" a frame with whatever you want in the screen. For example:

def help_screen(parent):
    screen = Frame(parent, ...)
    label = Label(screen, ...)
    ...
    return screen

def other_screen(parent):
    screen = Frame(parent, ...)
    ...
    return screen

Then, your main program only needs to hide or destroy the screen itself, rather than try to hide all the widgets on the screen:

def show_screen(screen):
    global current_screen
    if current_screen is not None:
        current_screen.pack_forget()
    current_screen = screen
    screen.pack(...)

Your initial code might look something like this:

help = help_screen(root)
other = other_screen(root)
current_screen = None
show_screen(help_screen)

I wouldn't literally write my code this way, but it shows the general concept: make each screen a Frame with widgets, and then hide/show one frame at a time. This is much more scaleable than to have hundreds of widgets you have to remember to hide or show.

For an object-oriented approach to managing multiple screens, see this question:

Switch between two frames in tkinter

Community
  • 1
  • 1
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685