Tova
Tova

Reputation: 25

presenting menus in tkinter

I'm writing a connect-4 game with Tkinter, and I would to present several menu options to the user during the course of the game.

The problem is that the menus tend to be presented together, as in the piece of code below. For example, in present_player_choice(), I'd like to present a menu for playerA, get an answer, and then present a menu for playerB. This is not that crucial here, but it's a problem I keep running across.

after() does not seem to be the answer, as I do not want the menu to disappear after a certain space of time, but rather to disappear after the user has submitted an answer.

Also: In writing an 'ok' button for the menu, I've used 'quit.' But quit closes the entire widget! I want the gui to continue, and simply the menu to close, not the entire GUI!

I know these questions sound rather clueless, but I've been working on this for a while and am genuinely confused. Thanks in advance for any help.

from tkinter import *
class GUI:

def __init__(self, root):
    self.__root = root
    self.__player_A = None
    self.__player_B = None

def assign_player(self, player, identity):
    if player == "player A":
        self.__player_A = identity
    elif player == "player B":
        self.__player_B = identity
    print("Player A is:  " + str(self.__player_A))
    print("Player B is:  " + str(self.__player_B))

def present_player_choice(self):
    self.ask_choose_player("player A")
    self.ask_choose_player("player B")
    Button(self.__root, text="OK", command=quit).pack(anchor=W)

def ask_choose_player(self, player):

    Label(self.__root, text="Who would you like to play " + player + "?").pack(anchor=W)
    var = IntVar()
    Radiobutton(self.__root, text="human", variable=var,
                command=lambda:self.assign_player(player, HUMAN), value=1).pack(anchor=W)
    Radiobutton(self.__root, text="computer", variable=var,
                command=lambda:self.assign_player(player, COMPUTER), value=2).pack(anchor=W)


if __name__ == '__main__':

root = Tk()
gui = GUI(root)
gui.present_player_choice()
mainloop()

Upvotes: 1

Views: 96

Answers (1)

Mike - SMT
Mike - SMT

Reputation: 15236

The quickest way to do this is to add a Frame to your class that we can use to reset the content and then move the call for player B into a condition in the assign_player method to update the frame for player B when a selection is chosen.

You may also want to add tristatevalue=0 to your radio buttons so that there is no default selection.

Example:

import tkinter as tk


class GUI:
    def __init__(self, root):
        self.__root = root
        self.__player_A = None
        self.__player_B = None
        self.frame = None

    def assign_player(self, player, identity):
        if player == "player A":
            self.__player_A = identity
            print("Player A is:  " + str(self.__player_A))
            self.ask_choose_player("player B")
            tk.Button(self.__root, text="OK", command=quit).pack(anchor=tk.W)
        elif player == "player B":
            self.__player_B = identity
            print("Player B is:  " + str(self.__player_B))
            self.frame.destroy()

    def present_player_choice(self):
        self.ask_choose_player("player A")

    def ask_choose_player(self, player):
        if self.frame is None:
            self.frame = tk.Frame(self.__root)
        else:
            self.frame.destroy()
            self.frame = tk.Frame(self.__root)

        self.frame.pack(fill='both', expand=1)
        tk.Label(self.frame, text="Who would you like to play " + player + "?").pack(anchor=tk.W)
        var = tk.IntVar()

        tk.Radiobutton(self.frame, text="human", variable=var, tristatevalue=0,
                       command=lambda: self.assign_player(player, 'human'), value=1).pack(anchor=tk.W)
        tk.Radiobutton(self.frame, text="computer", variable=var, tristatevalue=0,
                       command=lambda: self.assign_player(player, 'pc'), value=2).pack(anchor=tk.W)


if __name__ == '__main__':
    root = tk.Tk()
    gui = GUI(root)
    gui.present_player_choice()
    root.mainloop()

Before/after selection:

enter image description here

enter image description here

Upvotes: 1

Related Questions