【问题标题】:Calling functions from a Tkinter Frame to another从 Tkinter 框架调用函数到另一个框架
【发布时间】:2018-07-21 17:10:03
【问题描述】:

我有一个页面,我将在其中显示一些客户的详细信息。因此,我创建了一个名为“客户详细信息”的页面,其中包含我需要的所有标签,并将这些标签的文本设置为变量。太糟糕了,它不起作用。标签是在 __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()

【问题讨论】:

标签: python function class tkinter frame


【解决方案1】:

要调用另一个对象的方法,您需要对该对象的引用。您复制的用于管理不同页面的代码旨在简化此操作,但缺少获取页面实例的功能。

所以,首先你需要做的是在控制器上添加一个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()

【讨论】:

    【解决方案2】:

    您可以考虑保存对您需要更新的 GUI 字段的引用,例如,您的 MyApp 类中的字典。这样,您就可以从类中的任何位置访问它们,而不管实际的 GUI 元素恰好放置在哪里。

    GUI 编程通常会产生非常混乱的类,使用 dict 来跟踪元素可以减少混乱。其他人喜欢为您以后需要访问的每个元素保留单独的类属性。

    【讨论】:

    • 我想我不明白。您的意思是在 MyApp 类中为所有窗口创建小部件?
    • 一个类可以创建多个 tk.Frame 实例并根据需要跟踪每个 tk.Frame 中包含的小部件。
    猜你喜欢
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 2018-10-31
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多