首页 > 解决方案 > 在 tkinter GUI 中使用来自另一个类(不同页面)的变量

问题描述

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

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

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

只有当我定义一个自定义函数时它才会起作用,例如通过 name 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()

标签: pythonclasstkinter

解决方案


你不能使用command=p2.liftif p2doesn't exist - 因为它试图找到lift分配p2command=它却找不到p2

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

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

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

command=p1.listinPage2没有问题,因为p1它在执行时已经存在,但我使用['command']两个按钮使代码相同)

这也意味着你必须使用self.for self.buttonToP1,self.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()

推荐阅读