Как правильно получить доступ к функциям класса из другого Python класса - PullRequest
0 голосов
/ 30 октября 2018

Скажем, у меня есть коллекция классов, использующих Tkinter:

class MAIN(tk.Tk):
    def __init__(self, *args):
    ...
class Page1(tk.Frame): #Login page Frame
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        ...
        def Method(self):
        ...
class Page2(tk.Frame): 
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        ...

Скажите, Page2 нужно использовать Method(self) из Page1, как бы это было разработано? Предполагая, что у нас есть кадры Tkinter, каждый кадр записывается в формате класса со всеми кадрами, инициированными в классе MAIN.

То, что я сейчас пытаюсь сделать безуспешно, - это заставить страницу моего главного меню обновить свой список, который принимает и отображает аргументы из базы данных. Например, когда я вставляю другую строку в БД, используя Page2, она должна вернуть меня к Page1, однако Page1 является статическим и не обновляется. Я изучаю пользовательский интерфейс, и застрял на этом в течение нескольких дней. У меня есть функция, которая удаляет аргументы списка, и функция для отображения аргументов снова, но они находятся в Page1, и как только я подниму Page1 обратно из Page2, Page1 не будет обновлять аргументы.

РЕДАКТИРОВАТЬ: Это класс с методом, который мне нужно использовать в другом месте (Продолжить ниже)

class mainMenuPage(tk.Frame): #Main Menu Frame, consists of the main navigation page, List box
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        self.controller = controller

        self.listBox()


        #self.listBox_delete(numrow)

        self.label = tk.Label(self, text="Search employee by typing his/her last name:")
        self.label.grid(row=0, column=1)

        self.entry_username = tk.Entry(self)
        self.entry_username.grid(row=0, column=3)


        button = tk.Button(self, text='Add Employee', width=15,
                            command=lambda: (controller.clear_shared_data(), controller.raise_frame(addEmpFrame)))
        button.grid(row=2, column=3)
        button = tk.Button(self, text='Remove Employee', width=15, command=lambda: controller.raise_frame(removeEmpFrame))
        button.grid(row=3, column=3)
        button = tk.Button(self, text='Employee Lookup', width=15, command=lambda: controller.raise_frame(EmpLookupFrame))
        button.grid(row=4, column=3)
        button = tk.Button(self, text='Calculate Pay Roll', width=15, command=lambda: controller.raise_frame(calcPayRollFrame))
        button.grid(row=5, column=3)

    def listBox(self):
        self.row = []

        self.scrollbar = tk.Scrollbar(self)
        self.scrollbar.grid(row=2, column=2)

        connection: Connection = pymysql.connect(host='localhost',
                                                 port=3306,
                                                 user='root',
                                                 password='root',
                                                 db='hrdb')
        cursorObject = connection.cursor()
        cursorObject.execute('SELECT `firstName`,`lastName` from `employeeprofile`')
        numrows = int(cursorObject.rowcount)
        for x in range(0, numrows):
            self.row.append(cursorObject.fetchone())

        self.list1 = tk.Listbox(self, height=10, width=35)
        for x in self.row:
            self.list1.insert(END, x)
        self.list1.grid(row=2, column=0, columnspan=2)

        self.scrollbar.config(command=self.list1.yview)

        return numrows

    def listBox_delete(self, numrow):
        self.list1 = tk.Listbox(self, height=10, width=35)
        for x in range(0, numrow):
            self.list1.delete('0', 'end')
        self.list1.grid(row=2, column=0, columnspan=2)
        self.list1 = tk.Listbox(self, height=10, width=35)

Класс, который является фреймом моего пользовательского интерфейса, в основном представляет собой навигатор главного меню со списком значений из mySQL. Проблема здесь в том, что после использования любого другого фрейма или операции в программе, которая возвращает меня в главное меню, программа не обновляет список list1, т.е. когда я добавляю в систему employee, новый сотрудник отображается в списке только после перезапуска приложения. (Методы работают с БД). Я знаю, что причина в том, что фрейм статичен, и мой список создается один раз, и с тех пор ничем не манипулируют, но я не могу найти способ в основном генерировать список каждый раз, когда фрейм вызывается, и, в свою очередь, получать все значения из базы данных снова, чтобы обновить список.

1 Ответ

0 голосов
/ 30 октября 2018

Единственный способ ссылаться на один кадр из другого - через контроллер. Рассмотрим этот пример:

import tkinter as tk

class MAIN(tk.Tk):
    def __init__(self, *args):
        tk.Tk.__init__(self)

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

        self.frames = {}
        for F in (Page1, Page2):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame

            frame.grid(row=0, column=0, sticky="nsew")

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()

    def get_frame(self, page_name):
        frame = self.frames[page_name]
        return frame


class Page1(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        tk.Label(self, text='Page 1').pack()

    def Method(self):
        print('Page 1 method')


class Page2(tk.Frame): 
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        tk.Label(self, text='Page 2').pack()
        tk.Button(self, text='Raise Page 1 and execute function', command=self.exit).pack()

    def exit(self):
        self.controller.show_frame("Page1")
        self.controller.get_frame("Page1").Method()


app = MAIN()
app.mainloop()

Page1 не имеет ссылки на Page2, но имеет controller, которая является ссылкой на экземпляр MAIN. Поскольку MAIN является контроллером, он «знает» все кадры. Я дал MAIN метод get_frame, который возвращает ссылку на фрейм по его имени. Поэтому для ссылки Page1 из любого другого фрейма вы можете сделать self.controller.get_frame("Page1"). Чтобы затем вызвать метод Method(), просто добавьте его, чтобы сделать self.controller.get_frame("Page1").Method()

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


Еще один способ выполнить то, что вы хотите, это убедиться, что метод вызывается каждый раз, когда Page1 становится видимым, для этого следуйте объяснениям в ответе на Как бы я создал метод который запускается каждый раз, когда кадр отображается в tkinter .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...