Python 在tkinter GUI中使用来自另一个类(不同页面)的变量

Python 在tkinter GUI中使用来自另一个类(不同页面)的变量,python,class,tkinter,Python,Class,Tkinter,我有一个由不同页面组成的应用程序,这些页面都放在一个框架内(带有状态栏、菜单栏等),并堆叠在彼此的顶部。通过调用函数lift,我可以将各个页面置于其他页面之上。(这是一个最低可行的示例,整个程序大约有2000行) 当我从菜单栏中调用p1.lift时,第1页显示在前面-当我尝试第2页上的“从”按钮时,它会告诉我未定义名称p2。我明白了,因为我在MainView类中只引用了Page2(self)作为p2 如果我将按钮命令更改为command=Page2(self).lift,则代码将运行,但按钮没有

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

当我从菜单栏中调用
p1.lift
时,第1页显示在前面-当我尝试第2页上的“从”按钮时,它会告诉我未定义
名称p2
。我明白了,因为我在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()

如果
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
command=p1.list
Page2
中不会出现问题,因为执行时
p1
已经存在,但我对两个按钮使用
['command']
使代码相同)

这还意味着您必须将
self.
用于
self.buttonop1
self.buttonop2

完整代码:

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()
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()

编辑:其他方法是将函数用作类中的方法。然后分配现有方法
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)
        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()
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()

带着我的非CS背景,我已经走了很长一段路,但无论什么时候开始上课,我还是不明白。例如,我将类Page2的实例创建为p2,但我不知道(尽管谷歌搜索了这么多…)如何从另一个类中访问它。请阅读给定链接并关注
实例变量
“此处忽略一些重要概念”:将
p2
定义为
实例变量后,可以执行
command=self.master.p2.lift
.master
tkinter
对象中的默认引用属性。我投票决定关闭它,因为这个问题很可能只是因为缺乏基本的OOP(?)知识,我看不出它对其他人特别有用。