Вызов метода / подкласса GUI из отдельного класса - PullRequest
0 голосов
/ 22 октября 2019

Я пытаюсь создать сценарий, который создает экземпляр класса GUI, который сам по себе имеет подклассы для представления различных страниц, которые я хочу отобразить.

Цель состоит в том, чтобы создать файл последовательности, который вызывает конкретную страницу графического интерфейса для отображения, и как только эта страница графического интерфейса отображается и нажимается кнопка, она запускает последовательность из файла последовательности, который затем определяет, какой графический интерфейс пользователяотображаемых страниц.

Seqeuncer выглядит примерно так (критерии для отображения тестовых страниц упрощены)

import gui

class Sequencer():

    def __init__(self):
        pass

    def run_gui(self):
        # Create instance of the Test GUI
        self.my_gui = gui.TestGUI()
        self.my_gui.mainloop()

    def run_test(self, entry):
if x = 1:
        gui.TestGUI().show_page(PageOne)
if x = 2:
        gui.TestGUI().show_page(PageTwo)

Графический интерфейс выглядит так:

import sequencer

class TestGUI(tk.Tk):

    def __init__(self):

        # Initialize the container
        tk.Tk.__init__(self)
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # Make the container a fixed size
        tk.Tk.resizable(self, False, False)

        # Set up the pages for the GUI
        self.pages = {}
        list_of_pages = [
            PageOne,
            PageTwo
        ]
        for P in list_of_pages:
            frame = P(container, self)
            self.pages[P] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        # Set the Main Page
        self.show_page(MainPage)

    def show_page(self, page):

        frame = self.pages[page]
        frame.tkraise()

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)

        entry = tk.Entry(self, width=40, font="Arial 16", justify="center")
        entry.place(relx=0.5, rely=0.5, anchor="center")

        # Create Binding for the Return Key
        entry.bind("<Return>", lambda event: sequencer.Sequencer().run_test(entry.get()))

class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)

Я тогдасоздайте скрипт верхнего уровня (main.py), который создает экземпляр Sequencer и запускает графический интерфейс. Вместо того, чтобы показывать страницы, которые должны быть показаны, я получаю сообщение об ошибке.

Я делаю это неправильно?

1 Ответ

0 голосов
/ 22 октября 2019

Вы не должны создавать новый экземпляр Sequencer. Вместо этого передайте ссылку или предоставьте другим классам способ доступа к экземпляру.

Что я хотел бы сделать, это передать секвенсор в ваш графический интерфейс следующим образом:

class Sequencer():
    def run_gui(self):
        ...
        self.my_gui = gui.TestGUI(sequencer=self)
        ...

class TestGUI(tk.Tk):
    def __init__(self, sequencer):
        self.sequencer = sequencer
        ...

Потому чтокаждой вашей подстранице дан экземпляр TestGUI в качестве контроллера, вы можете сослаться на существующий секвенсор, удалив импорт и затем используя контроллер для получения ссылки на секвенсор:

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        ...
        self.controller = controller
        ...

        entry.bind("<Return>", lambda event: self.controller.sequencer.run_test(entry.get()))

Хотя,код будет легче читать и отлаживать, если вы замените lambda на соответствующую функцию. Я считаю хорошим правилом никогда не использовать lambda, если вы абсолютно не обязаны. В этом случае на самом деле нет никакого преимущества в использовании lambda.

Пример:

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        ...
        self.entry = tk.Entry(...)
        self.entry.bind("<Return>", self.run_test)
        ...

    def run_test(self):
        data = self.entry.get()
        self.controller.sequencer.run_test(data)

При этом отладка кода становится намного проще, поскольку вы можете просматривать данныедо звонка run_test. В этом простом случае это может не потребоваться, но если вы привыкнете к такому кодированию, это пригодится, когда вы будете выполнять более сложные команды.

Вам также нужно изменить run_testфункция для повторного использования существующего экземпляра TestGUI вместо создания нового каждый раз.

def run_test(self, entry):
    ...
        self.mygui.show_page(PageOne)
    ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...