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




function class (2)

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

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

У меня есть страница, где я покажу некоторые детали клиентов. Поэтому я создал страницу под названием «Сведения о клиентах» со всеми необходимыми ярлыками и установил текст этих ярлыков в качестве переменных. Жаль, что это не работает. Метки создаются в методе __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()

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

Итак, первое, что вам нужно сделать, это добавить метод 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()




frame