【问题标题】:using variables from another class (different Pages) in tkinter GUI在 tkinter GUI 中使用来自另一个类(不同页面)的变量
【发布时间】:2020-01-08 19:49:53
【问题描述】:

我有一个由不同页面组成的应用程序,这些页面都放置在一个框架内(带有状态栏、菜单栏等)并相互堆叠。通过调用函数lift,我可以将相应的页面置于其他页面之上。 (这是一个最小的可行示例,完整的程序大约有 2000 行)

当我从菜单栏中调用 p1.lift 时,第 1 页会显示在前面 - 当我从第 2 页上的按钮尝试相同操作时,它会告诉我 name p2 is not defined。我明白了,因为我只在 MainView 类中将Page2(self) 引用为p2

如果我将按钮命令更改为command=Page2(self).lift,代码会运行,但按钮不执行任何操作。我还尝试通过partial 模块传递带参数的函数,但仍然没有运气。

只有当我定义一个自定义函数时它才会起作用,例如名称为LiftP2,它只做类本身可以做的事情——p2.lift()

我想知道是否有人可以向我解释为什么我需要使用该解决方法以及如何以与从菜单相同的方式访问它...因为我没有编写这些类(而是从其他 SO 答案生成它们: )) 显然在这里错过了一些重要的概念,我很乐意为所描述的问题提供任何帮助。

import tkinter as tk


class Page(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
    def show(self):
        self.lift()


class Page1(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        buttonToP1 = tk.Button(self, text='Go to Page 2', command=LiftP2)
        buttonToP1.pack(fill=tk.X)


class Page2(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        buttonToP2 = tk.Button(self, text='Go to Page 1', command=LiftP1, bg='yellow')
        buttonToP2.pack(fill=tk.X)


class MainView(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        global p1,p2
        p1 = Page1(self)
        p2 = Page2(self)

        mainMenu = tk.Menu(self)
        root.config(menu=mainMenu)
        mainMenu.add_command(label='Navigate to Page 1', command=p1.lift)
        mainMenu.add_command(label='Navigate to Page 2', command=p2.lift)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)

        p1.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p2.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p1.show()


def LiftP1():
    p1.lift()
def LiftP2():
    p2.lift()


if __name__ == "__main__":
    root = tk.Tk()
    main = MainView(root)
    main.pack(side="top", fill="both", expand=True)  
    root.title('Testapplication v01')
    root.wm_geometry('%dx%d+%d+%d' % (300, 200, 100, 100))
    root.mainloop()

【问题讨论】:

  • 我的非 CS 背景已经走得很远了,但是每当课程开始发挥作用时,我还是不明白。这里例如我将 Page2 类的实例创建为 p2,但我不知道(尽管谷歌搜索...)如何从另一个类中访问它。
  • 阅读给定的链接并关注Instance variable
  • “错过了一些重要的概念”:将p2 定义为Instance variable 后,您可以执行command=self.master.p2.lift.mastertkinter 对象中的默认引用属性。
  • 我投票结束这个问题,因为这个问题很可能只是由于缺乏基本的 OOP (?) 知识而引起的,而且我看不出它对其他人特别有用。

标签: python class tkinter


【解决方案1】:

如果p2 不存在,则不能使用command=p2.lift - 因为它试图在p2 中查找lift 以分配给command=,但找不到p2

所以首先你必须创建实例(在按钮中没有command=),然后你必须在按钮中分配command=

    p1 = Page1(self)
    p2 = Page2(self)

    p1.buttonToP1['command'] = p2.lift
    p2.buttonToP2['command'] = p1.lift

Page2 中的command=p1.list 不会产生问题,因为p1 在执行时已经存在,但我使用['command'] 两个按钮使代码相同)

这也意味着您必须将self. 用于self.buttonToP1self.buttonToP2

完整代码:

import tkinter as tk

class Page(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
    def show(self):
        self.lift()

class Page1(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        self.buttonToP1 = tk.Button(self, text='Go to Page 2')
        self.buttonToP1.pack(fill=tk.X)

class Page2(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        self.buttonToP2 = tk.Button(self, text='Go to Page 1', bg='yellow')
        self.buttonToP2.pack(fill=tk.X)

class MainView(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        #global p1,p2
        p1 = Page1(self)
        p2 = Page2(self)

        p1.buttonToP1['command'] = p2.lift
        p2.buttonToP2['command'] = p1.lift

        mainMenu = tk.Menu(self)
        root.config(menu=mainMenu)
        mainMenu.add_command(label='Navigate to Page 1', command=p1.lift)
        mainMenu.add_command(label='Navigate to Page 2', command=p2.lift)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)

        p1.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p2.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p1.show()

if __name__ == "__main__":
    root = tk.Tk()
    main = MainView(root)
    main.pack(side="top", fill="both", expand=True)  
    root.title('Testapplication v01')
    root.wm_geometry('%dx%d+%d+%d' % (300, 200, 100, 100))
    root.mainloop()

编辑: 其他方法是将您的函数用作类中的方法。然后你分配现有的方法command=self.change 这样就没有问题了

class Page1(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        buttonToP1 = tk.Button(self, text='Go to Page 2', command=self.change)
        buttonToP1.pack(fill=tk.X)

    def change(self):
        p2.lift()

class Page2(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        buttonToP2 = tk.Button(self, text='Go to Page 1', command=self.change, bg='yellow')
        buttonToP2.pack(fill=tk.X)

    def change(self):
        p2.lift()

完整代码:

import tkinter as tk

class Page(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
    def show(self):
        self.lift()

class Page1(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        buttonToP1 = tk.Button(self, text='Go to Page 2', command=self.change)
        buttonToP1.pack(fill=tk.X)

    def change(self):
        p2.lift()

class Page2(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        buttonToP2 = tk.Button(self, text='Go to Page 1', command=self.change, bg='yellow')
        buttonToP2.pack(fill=tk.X)

    def change(self):
        p2.lift()

class MainView(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)

        global p1, p2

        p1 = Page1(self)
        p2 = Page2(self)

        mainMenu = tk.Menu(self)
        root.config(menu=mainMenu)
        mainMenu.add_command(label='Navigate to Page 1', command=p1.lift)
        mainMenu.add_command(label='Navigate to Page 2', command=p2.lift)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)

        p1.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p2.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p1.show()

if __name__ == "__main__":
    root = tk.Tk()
    main = MainView(root)
    main.pack(side="top", fill="both", expand=True)  
    root.title('Testapplication v01')
    root.wm_geometry('%dx%d+%d+%d' % (300, 200, 100, 100))
    root.mainloop()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多