如何从另一个Class python

时间:2018-10-30 06:00:18

标签: python class user-interface tkinter

说我有一些使用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是静态的,不会更新。我正在学习UI,现在已经坚持了好几天。我有一个删除列表框参数的函数,以及一个再次显示参数的函数,但是,它们在Page1中,一旦我将Page1Page2备份起来,{{1 }}不会更新参数。

编辑:这是带有我需要在其他地方使用的方法的类(下面继续)

Page1

该类是UI的框架,基本上是一个主菜单导航器,带有来自mySQL的值的列表框。这里的问题是,在程序中使用了其他框架或操作使我回到主菜单之后,该程序将不会更新列表框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) ,即当我向系统中添加list1时,只有重新启动应用程序后,新雇员才会显示在列表框中。 (这些方法适用于db)。我知道原因是框架是静态的,并且我的列表框仅创建一次,此后没有任何操作,但是,我找不到一种基本上在每次调用框架时都生成列表框并反过来得到所有列表框的方法再次从数据库中获取值以更新列表框。

1 个答案:

答案 0 :(得分:1)

引用另一帧的唯一方法是通过控制器。考虑以下示例:

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可见时都调用一个方法,请按照the answer to How would I make a method which is run every time a frame is shown in tkinter中的说明进行操作。