TKinter - 尝试销毁按钮时的AttributeError

时间:2018-04-26 18:54:08

标签: python tkinter

Greetings Stack Overflowers!

请注意我是新手,我只是在学习。

我遇到以下错误:AttributeError: '_tkinter.tkapp' object has no attribute 'button_draw'

问题似乎的主要逻辑位于start_game_event。基本上,如果game_typewith draw,则必须创建按钮。但是,如果基于当前窗口制作新游戏并且该按钮仍然存在,我希望将其删除。我不确定是否还有另外一种方法可以解决这个问题,例如完全重新生成主框架,但这就是我站立的地方。

以下是代码:

from tkinter import Button, E, Frame, IntVar, Label, LEFT, messagebox, N, NE, Radiobutton, RIGHT, S, SW, StringVar, Tk, Toplevel, W

class DominoWindow(Tk):

    def __init__(self):
        super().__init__()

        self.nb_players_var = None
        self.type_partie = None

        self.title('Jeu de Pydomino!')
        self.resizable(width=False, height=False)

        self.frame_player_north = Frame(self)
        self.frame_player_west = Frame(self)
        self.frame_table = Frame(self, borderwidth=2)
        self.frame_player_est = Frame(self)
        self.frame_current_player = Frame(self)

        self.frame_player_north.grid(row=0, column=1)
        self.frame_player_west.grid(row=1, column=0)
        self.frame_table.grid(row=1, column=1)
        self.frame_player_est.grid(row=1, column=2)
        self.frame_current_player.grid(row=2, column=1)

        self.label_name_player_north = Label(self.frame_player_north)
        self.label_name_player_north.grid(row=0)
        self.label_hand_player_north = Label(self.frame_player_north)
        self.label_hand_player_north.grid(row=1)

        self.label_name_player_west = Label(self.frame_player_west)
        self.label_name_player_west.grid(row=0)
        self.label_hand_player_west = Label(self.frame_player_west)
        self.label_hand_player_west.grid(row=1)

        self.label_table = Label(self.frame_table, height=8, width=100)
        self.label_table.grid(row=0, column=0)

        self.label_name_player_east = Label(self.frame_player_est)
        self.label_name_player_east.grid(row=0)
        self.label_hand_player_east = Label(self.frame_player_est)
        self.label_hand_player_east.grid(row=1)

        self.label_name_current_player = Label(self.frame_current_player)
        self.label_name_current_player.grid(row=1)
        self.frame_hand_current_player = Frame(self.frame_current_player)

        self.button_quit = Button(self, text="Quitter", command=self.quit_party_event)
        self.button_quit.grid(row=3, column=2)

        self.button_new_game = Button(self, text="Nouvelle partie", command=self.introduction_game)
        self.button_new_game.grid(row=2, column=2)

        self.introduction_game()

    def show(self):

        if self.nb_players_var.get() == 2:
            self.label_name_player_north.config(text="Player 0")
            self.label_hand_player_north.config(text="[|]" * 6) #len(self.partie.donnes[self.partie.tour+1]))

            self.label_table.config(text="VARIABLE_TABLE")
            self.label_name_current_player.config(text="Player Current")

            self.label_name_player_east.config(text="")
            self.label_hand_player_east.config(text="")
            self.label_name_player_west.config(text="")
            self.label_hand_player_west.config(text="")

        elif self.nb_players_var.get() == 3:
            self.label_name_player_north.config(text="Player 0")
            self.label_hand_player_north.config(text="[|]" * 6) #len(partie.Partie.donnes[partie.tour+1]))

            self.label_name_player_east.config(text="Player 1")
            self.label_hand_player_east.config(text="[|]\n" * 6) #len(self.partie.donnes[self.partie.tour+2]))

            self.label_table.config(text="VARIABLE DU PLATEAU")
            self.label_name_current_player.config(text="Player Current")

            self.label_name_player_west.config(text="")
            self.label_hand_player_west.config(text="")

        elif self.nb_players_var.get() == 4:
            self.label_name_player_north.config(text="Player 0")
            self.label_hand_player_north.config(text="[|]" * 6) #len(self.partie.donnes[self.partie.tour+1]))

            self.label_name_player_east.config(text="Player 1")
            self.label_hand_player_east.config(text="[|]\n" * 6) #len(self.partie.donnes[self.partie.tour+2]))

            self.label_name_player_west.config(text="Player 3")
            self.label_hand_player_west.config(text="[|]\n" * 6) #len(self.partie.donnes[self.partir.tour+3]))

            self.label_table.config(text="VARIABLE_DU_PLATEAU")
            self.label_name_current_player.config(text="Player Current")

    def introduction_game(self):
        self.introduction_window_game = Toplevel(self, height=200, width=500)
        self.introduction_window_game.title("Choose your game settings!")
        self.introduction_window_game._root().lift()
        self.nb_players_var = IntVar()
        self.type_partie = StringVar()
        # Label(self.introduction_window_game, text="Choose your game settings!").pack()
        Label(self.introduction_window_game, text="\nWhat kind of game do you want?").pack()
        Radiobutton(self.introduction_window_game, text="Game without draw",
                    variable=self.type_partie, value="without draw").pack(anchor=W)
        Radiobutton(self.introduction_window_game, text="Game with draw",
                    variable=self.type_partie, value="with draw").pack(anchor=W)

        Label(self.introduction_window_game, text="\nCombien de Players voulez-vous?").pack()
        Radiobutton(self.introduction_window_game, text="2 Players",
                    variable=self.nb_players_var, value=2).pack(anchor=W)
        Radiobutton(self.introduction_window_game, text="3 Players",
                    variable=self.nb_players_var, value=3).pack(anchor=W)
        Radiobutton(self.introduction_window_game, text="4 Players",
                    variable=self.nb_players_var, value=4).pack(anchor=W)

        Button(self.introduction_window_game, text="Quit",
               command=self.quit_party_event).pack(side=RIGHT)
        Button(self.introduction_window_game, text="Ok",
               command=self.start_game_event).pack(side=RIGHT)

    def start_game_event(self):
        result = messagebox.askokcancel("Paramètres de partie",
                                        f"Vous avez choisi {self.nb_players_var.get()} Players et "
                                        f"le type de partie {self.type_partie.get()}."
                                        f"\nEst-ce exact?", icon='warning')
        if result == True:
            self.start_game()
            self.show()
            self.introduction_window_game.destroy()
            if self.type_partie.get() == "with draw":
                self.button_draw = Button(self, text="Draw", command=self.button_to_draw)
                self.button_draw.grid(row=3, column=0)
            else:
                self.button_draw.grid_remove()
                self.destroy

    def quit_party_event(self):
        result = messagebox.askokcancel("Quit the game.", "Are you sur?", icon='warning')
        if result == True:
            self.destroy()

    def button_to_draw(self):
        print("Function test. You drew a domino!")

    def message_fin_de_partie(self):
        pass

if __name__ == '__main__':
    DominoWindow().mainloop()

错误位于:self.button_draw.grid_remove()

谢谢,我希望一切都清楚。

已编辑:已删除依赖项并调整了变量名称。打字错误。

1 个答案:

答案 0 :(得分:0)

我首先要说的是,由于self.start_game()方法不存在,我已将start_game行注释掉了。我还要补充一点,重现问题,我启动了应用程序,然后选择开始一个没有任何数量的玩家抽奖的游戏。

最终,你可能会做你想要的事情:即并不总是有' Draw'按钮。我要做的是在self.button_draw = None()内的某处添加行__init__。这可以确保您的窗口始终具有button_draw属性,因此可以删除有关此属性的AttributeError

接下来,您需要调整if中较低的start_game_event()语句,以删除“绘制”字样。网格中的按钮如果已创建:

        if self.type_partie.get() == "with draw":
            self.button_draw = Button(self, text="Draw", command=self.button_to_draw)
            self.button_draw.grid(row=3, column=0)
        elif self.button_draw is not None:
            self.button_draw.grid_remove()
            self.button_draw.destroy()
            self.button_draw = None

我已将else替换为elif且条件self.button_draw不是None:我们无法删除& #39;绘制'按钮,如果没有要删除的按钮。

另请注意,我已将self.destroy行替换为self.button_draw.destroy():如果您调用了该方法,前者会关闭您的应用但是您没有调用self.desroy没有。此外,一旦按钮被销毁,我们可以将self.button_draw设置回None,表示我们没有“抽奖”#39}。按钮。

以类似的方式,如果' Draw'按钮存在,你用绘图开始另一个游戏,你的窗口中有两个按钮。你只会看到一个,因为一个将在另一个之上。但是,由于您只保留对一个按钮的引用,因此您只能删除这两个按钮中的一个。我会让您对代码进行类似的修改,只有在按钮尚未存在的情况下才添加按钮。