Как правильно ссылаться на имена фреймов в tkinter - PullRequest
0 голосов
/ 29 января 2019

Я создаю карточную игру в tkinter и мне нужна помощь со ссылками на названия фреймов.Моя проблема в том, что когда я хочу «обновить» фрейм, мне нужно уничтожить и воссоздать его, и это изменит прогрессивную нумерацию фреймов.

Пожалуйста, посмотрите на код ниже.Пример показывает, что третий кадр каждый раз получает новое имя по мере воссоздания.

import tkinter as tk


class RootFrame(tk.Tk):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.main_window = tk.Frame(self)
        self.main_window.pack(side="top", fill="both", expand=True)
        self.main_label = tk.Label(self.main_window, text="Main Window")
        self.main_label.pack()

        self.second_frame = SecondFrame(self.main_window, self)
        self.second_frame.pack()


class SecondFrame(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.controller = controller

        label = tk.Label(self, text="Second Frame")
        label.pack()

        self.create_third_frame()

    def create_third_frame(self):
        self.third_frame = ThirdFrame(self, self.controller)
        self.third_frame.pack()

    def update_frame(self):
        self.third_frame.destroy()
        self.create_third_frame()


class ThirdFrame(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.controller = controller
        self.parent = parent

        label = tk.Label(self, text="Third Frame")
        label.pack()

        refresh_button = tk.Button(
            self, text="Resfresh", command=self.parent.update_frame)
        refresh_button.pack()

        print(self.winfo_name())


if __name__ == "__main__":
    app = RootFrame()
    app.mainloop()

Приведенный выше код используется для иллюстрации проблемы.Пожалуйста, запустите код, и вы увидите изменяющееся имя виджета в терминале.

Я использую winfo_parent и winfo_name в моем фактическом коде, чтобы создать различные условия для привязки кнопок.Например, если пользователь нажимает widget1 в frame6, происходит X, а когда я нажимаю widget8 в frame2, происходит Y. Это работает до тех пор, пока я destroy() не воссоздаю что-то, и все ломается.

Я полагаю, что использование winfo_name и winfo_parent для такого рода ссылок не является правильным способом обойти, но я действительно не могу думать ни о чем другом.

1 Ответ

0 голосов
/ 29 января 2019

Я не совсем уверен, что именно вы спрашиваете, но вы можете присвоить виджету конкретное имя:

def create_third_frame(self):
    self.third_frame = ThirdFrame(self, self.controller, name='testframe')
    self.third_frame.pack()

Тогда каждый раз имя создаваемого фрейма будет согласованным.

Вы также можете ссылаться на виджет по имени с помощью Tk().nametowidget(), см. Соответствующий ответ здесь: Можно ли искать виджет по имени в Tkinter?

>>> from Tkinter import *
>>> win = Tk()
>>> button = Button( Frame( win, name = "myframe" ), name = "mybutton" )
>>> win.nametowidget("myframe.mybutton")
<Tkinter.Button instance at 0x2550c68>

Однако я бы порекомендовал придерживаться подхода ООП и просто сослаться на него из своего кода, например self.thirdframes, где у вас может быть list или dict из ThirdFrame объектов.Таким образом, ваш код Python может легко ссылаться на объекты, не возвращаясь к интерпретатору tcl и не анализируя имя виджета.Если у вас когда-либо будет только один ThirdFrame, тогда просто возвращайтесь к self.thirdframe всякий раз, когда вам это нужно.

...