TKinter - AttributeError при попытке уничтожить кнопку - PullRequest
0 голосов
/ 26 апреля 2018

Привет, переполнение стека!

Обратите внимание, что я новичок и только учусь.

У меня следующая ошибка: AttributeError: '_tkinter.tkapp' object has no attribute 'button_draw'

Основная логика, в которой проблема, кажется, находится в start_game_event. Если game_type равен with 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 голосов
/ 26 апреля 2018

Начну с того, что закомментировал строку self.start_game(), так как метод start_game не существует. Я также добавлю, что для воспроизведения проблемы я запустил приложение и затем решил начать игру без ничьей с любым количеством игроков.

В конечном итоге возможно сделать то, что вы хотите: то есть не всегда есть кнопка «Рисовать». Я бы добавил строку 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: мы не можем удалить кнопку «Рисовать», если нет кнопки для удаления.

Заметьте также, что я заменил строку self.destroy на self.button_draw.destroy(): первая закроет ваше приложение, если бы вы вызвали метод, но, как вы не вызывали self.desroy, он ничего не сделал. Кроме того, после уничтожения кнопки мы можем установить self.button_draw обратно на None, чтобы показать, что у нас нет кнопки «Рисовать».

Аналогичным образом, если кнопка «Рисовать» существует, и вы начинаете другую игру с ничьей, в вашем окне будут две кнопки. Вы увидите только один, потому что один будет поверх другого. Однако, поскольку вы сохраняете ссылку только на одну кнопку, вы сможете удалить только одну из этих двух кнопок. Я оставлю на ваше усмотрение внести аналогичные изменения в ваш код, чтобы добавить кнопку, только если она еще не существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...