简体   繁体   中英

PYTHON TKINTER - destroying frames

I am trying to build a "Number Guessing Game" using tkinter , where you need to guess the number generated by the computer, by entering it in an Entry widget.

This is the code:

import tkinter as tk
import random, sys


class GameWindow(tk.Frame):

    def __init__(self, parent):

        tk.Frame.__init__(self, parent, bg="#8ECEBD")
        self.parent = parent

        self.init_window()
        self.cust_game()

        self.actual_num = self.create_num()


    def init_window(self):

        self.parent.geometry("800x900+560+90")
        self.parent.title("Guess The Number!")

        self.scrollbar = tk.Scrollbar(self)
        self.scrollbar.pack(side="right", fill="y")

        exit_button = tk.Button(self, bg="#811B14", font="Helvetica 17 bold",
                                command=lambda: self.client_exit(), text="EXIT GAME!",
                                cursor="hand2", relief="groove")
        exit_button.pack(fill="x", pady=10, padx=10)

        welcome_label = tk.Label(self, bg="#8ECEBD", fg="#810007", text="Welcome to\nGUESS THE NUMBER!",
                                 font="Helvetica 25 bold")
        welcome_label.pack(pady=60)


    def cust_game(self):

        self.main_frame = tk.Frame(self, bg="#8ECEBD")
        self.main_frame.pack(fill="x")

        instructions_label = tk.Label(self.main_frame, bg="#8ECEBD", fg="#6F8100", font="Helvetica 15",
                                      text="Enter a number between 0 and 100 down here:")
        instructions_label.pack(pady=15)

        self.entry = tk.Entry(self.main_frame, width=3, font="Helvetica 13 italic")
        self.entry.pack()

        submit_button = tk.Button(self.main_frame, text="Check!", font="Helvetica 13 bold", fg="#001F4C",
                                  relief="groove", bg="#336600", activebackground="#254C00", cursor="hand2",
                                  command=lambda: self.compare_numbers())
        submit_button.pack(pady=5)

        self.second_frame = tk.Frame(self, bg="#8ECEBD")
        self.second_frame.pack(pady=30)

        label = tk.Label(self.second_frame, bg="#8ECEBD", text="YOUR RESULTS:", font="Helvetica 15", fg="blue")
        label.pack(pady=15)

        self.answersbox = tk.Listbox(self.second_frame, bg="#8ECEBD", relief="groove", bd=0, height=13, width=39,
                                yscrollcommand=self.scrollbar.set, fg="#FF4800", font="Helvetica 15")
        self.answersbox.pack()

        self.scrollbar.config(command=self.answersbox.yview)


    def compare_numbers(self):


        num = self.entry.get()

        if len(num) == 0:
            self.answersbox.insert(0, "Please enter a number!\n")
        elif int(num) > 100 or int(num) < 0 :
            self.answersbox.insert(0, "You have to enter a number between 0 and 100!\n")
        elif int(num) > self.actual_num:
            self.answersbox.insert(0, "Too HIGH!\n")
        elif int(num) < self.actual_num:
            self.answersbox.insert(0, "Too LOW!\n")
        elif int(num) == self.actual_num:
            self.answersbox.insert(0, "Congratulations! The number was {}!\n".format(self.actual_num))

            new_button = tk.Button(self.second_frame, bg="#CC8E1A", fg="#001F4C",
                                   text="PLAY AGAIN!", font="Helvetica 13 bold", activebackground="#815B14",
                                   cursor="hand2", padx=100, pady=10, relief="groove",
                                   command=lambda: self.restart_game())
            new_button.pack(pady=15)

        self.entry.delete(0, tk.END)


    def create_num(self):

        return random.randint(0, 100)


    def client_exit(self):

        sys.exit("DONE!")


    def restart_game(self):

        self.main_frame.destroy()
        self.second_frame.destroy()

        self.cust_game()


root = tk.Tk()
app = GameWindow(root)
app.pack(fill="both", expand=True)
root.mainloop()

I am sorry if the code is too long to read. I've reached the point where, after the user guesses the number, he gets asked if he wants to play again, by pressing a Button . I am thinking, that when the button gets pressed, the two frames ( main_frame and second_frame ) need to get deleted with the help of the command .destroy() , but nothing seems to happen, when the button gets pressed. Please tell me what I'm doing wrong and if there's a better way to do this.

When you click new_button , restart_game is called and the two frames are destroyed. They don't appear so because restart_game then calls cust_game which recreates the two frames.

Inserting a few print s can help you understand the flow:

def cust_game(self):
    self.main_frame = tk.Frame(self, bg="#8ECEBD")
    self.main_frame.pack(fill="x")
    print('main_frame created')  # insert this
    # ...
    self.second_frame = tk.Frame(self, bg="#8ECEBD")
    self.second_frame.pack(pady=30)
    print('second_frame created')  # insert this

def restart_game(self):
    self.main_frame.destroy()
    print('main_frame destroyed')  # insert this
    self.second_frame.destroy()
    print('second_frame destroyed')  # insert this
    self.cust_game()   # note cust_game is called

Then when you first start the game, it prints to the console:

main_frame created
second_frame created

And when you click to play again, it prints

main_frame destroyed
second_frame destroyed
main_frame created
second_frame created

BTW, command=lambda: f() is superfluous. Just do command=f ; eg, command=self.restart_game .

You can use tkMessageDialog to ask user to play again:

import tkMessageBox
#... code

elif int(num) == self.actual_num:
    self.answersbox.insert(0, "Congratulations! The number was {}!\n".format(self.actual_num))
    if tkMessageBox.askyesno("Play", "play again?"):
        self.answersbox.delete(0, END)
    else:
        sys.exit("DONE!")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM