использование переменных из другого класса (разных страниц) в tkinter GUI - PullRequest
0 голосов
/ 08 января 2020

У меня есть приложение, состоящее из разных страниц, которые все размещаются внутри фрейма (со строкой состояния, строкой меню и т. Д. c.) И накладываются друг на друга. Вызвав функцию 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()

1 Ответ

1 голос
/ 08 января 2020

Нельзя использовать command=p2.lift, если p2 не существует - потому что он пытается найти lift в p2 для присвоения 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.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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...