Вызов функций из фрейма Tkinter в другой

У меня есть страница, где я покажу некоторые детали клиентов. Поэтому я создал страницу под названием "Сведения о клиентах" со всеми необходимыми ярлыками и установил текст этих ярлыков в качестве переменных. Жаль, что это не работает. Ярлыки создаются в __init__ метод, поэтому я не могу их "обновить", потому что init вызывается только в начале. Поэтому я подумал о том, чтобы создать новую функцию, содержащую все метки, и я вызову эту функцию, когда у меня возникнет такая необходимость... вот в чем проблема. Я не могу вызвать функцию в другом tk.Frame, Следующий код является упрощенной версией кода.

import tkinter as tk
from tkinter import ttk

class Myapp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container = ttk.Frame(self, borderwidth=10, relief="sunken", width=200, height=100)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (HomePage, PageOne):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="N,S,E,W")
        self.show_frame(HomePage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()


class HomePage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = ttk.Label(self, text="HomePage")
        label.pack()
        button1 = ttk.Button(self, text="Quit",
                            command=lambda: quit())
        button1.pack()
        button2 = ttk.Button(self, text="Call Function in the other page/class to show the label",
                            command=lambda: PageOne.function()) # this is to do it from an other class. I can't do this
        button2.pack()
        button3 = ttk.Button(self, text="Page One",
                            command=lambda: controller.show_frame(PageOne))
        button3.pack()


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = ttk.Label(self, text="PageOne")
        label.pack()
        button1 = ttk.Button(self, text="Quit",
                            command=lambda: quit())
        button1.pack()
        button2 = ttk.Button(self, text="Call Function, in local it works..",
                            command=lambda: self.function())#this is to do it in local
        button2.pack()
        button3 = ttk.Button(self, text="HomePage",
                            command=lambda: controller.show_frame(HomePage))
        button3.pack()

    def function(self):
        label1 = ttk.Label(self, text="It Worked!")
        label1.pack()


app = Myapp()
app.mainloop()

2 ответа

Чтобы вызвать метод для другого объекта, вам нужна ссылка на объект. Код, который вы скопировали для управления различными страницами, призван упростить это, но в нем отсутствует функция для получения экземпляра страницы.

Итак, первое, что вам нужно сделать, это добавить get_page Метод на контроллере:

class Myapp(tk.Tk):
    ...
    def get_page(self, page_class):
        return self.frames[page_class]

С этим вы можете получить экземпляр страницы, а с экземпляром страницы вы можете вызвать метод.

Далее вам нужно сохранить ссылку на контроллер, чтобы вы могли вызывать его из других функций:

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        ...

Наконец, теперь вы можете использовать контроллер для получения страницы, а со страницей вы можете вызвать функцию.

Моя рекомендация не использовать lambda если вам это абсолютно не нужно, и в этом случае вам это не нужно. Гораздо проще писать и отлаживать код, когда вы используете правильные функции вместо lambda,

Например:

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        ...
        button2 = ttk.Button(..., command=self.do_button)
        ...

    def do_button(self):
        page = self.controller.get_page(PageOne)
        page.function()

Вы можете сохранить ссылки на поля GUI, которые вам необходимо обновить, например, в dict в вашем классе MyApp. Таким образом, вы можете получить к ним доступ из любого места в классе, независимо от того, где находится фактический элемент GUI.

Программирование GUI обычно создает довольно грязные классы, использование dict для отслеживания элементов уменьшает беспорядок. Другим нравится хранить отдельные атрибуты класса для каждого элемента, к которому вам нужно обращаться позже.

Другие вопросы по тегам