繁体   English   中英

Python Tkinter 从菜单栏选项调用方法时出错

[英]Python Tkinter error when calling method from menu bar option

从菜单栏上的显示选项运行 Page1 class 中定义的显示方法时出现以下错误:

 '_tkinter.tkapp' object has no attribute 'body_frm'

从 Page1 中的“显示”按钮运行时,该方法可以正常工作。

我创建了一个名为 self.page1 的 Page1 实例。 这用于从菜单栏调用方法:

file_menu.add_command(label='Display', command=lambda: self.page1.display(self))

我认为这里可能有问题,因为我使用的是 lambda 和 display(self)。

仅使用 command=self.page1.display,我得到以下错误:'_tkinter.tkapp' object has no attribute 'page1'

使用 lambda:self.page1.display,我没有收到错误,但该方法不起作用使用 lambda:self.page1.display(),我得到 TypeError:display()缺少 1 个必需的位置参数:'self'

来自页面按钮的调用使用 command=self.display 并且工作正常。

通过将 self.body_frm 更改为 Page1.body_frm,我可以在菜单栏和页面按钮上获得 function 的方法。 虽然这可行,但我不认为这是一个正确的实现。

代码:

import tkinter as tk
from tkinter import ttk


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('Method Test')
        self.geometry('500x300')

        # Create frame container
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # Create menu bar
        self.create_menu_frame(self)

        # Create a dictionary of frames
        self.frames = {}

        self.page1 = Page1
        self.page2 = Page2

        # Add the two page frames to the dictionary.
        for page_frame in (self.page1, self.page2):
            frame = page_frame(container, self)
            self.frames[page_frame] = frame
            frame.grid(row=0, column=0, sticky=tk.NSEW)

        # Switch Order Entry frame
        self.show_frame(self.page1)

    def create_menu_frame(self, container: ttk.Frame) -> None:
        # Create menu bar
        menu_bar = tk.Menu(container)

        # Create options for File menu
        file_menu = tk.Menu(menu_bar, tearoff=0)
        file_menu.add_command(
            label='Display', command=lambda: self.page1.display(self))
        file_menu.add_separator()
        file_menu.add_command(
            label='Page 1', command=lambda: self.show_frame(self.page1))
        file_menu.add_command(
            label='Page 2', command=lambda: self.show_frame(self.page2))
        file_menu.add_separator()
        file_menu.add_command(label='Exit', command=self.quit)

        # Assign file menu list to the File option
        menu_bar.add_cascade(label="File", menu=file_menu)

        # Assign assign menu bar to the window
        container.config(menu=menu_bar)

    def show_frame(self, cont: tk.Frame) -> None:
        frame = self.frames[cont]
        # Raises the specified frame to the top
        frame.tkraise()


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

        Page1.result_str = tk.StringVar(value='')

        # Create page frame sections
        self.header_frm = tk.Frame(self)
        self.header_frm.pack(side=tk.TOP)
        self.header_frm.grid_rowconfigure(0, weight=1)

        self.body_frm = tk.Frame(self)
        self.body_frm.pack()
        self.body_frm.grid_rowconfigure(0, weight=1)

        self.footer_frm = tk.Frame(self)
        self.footer_frm.pack()
        self.footer_frm.grid_rowconfigure(0, weight=1)

        # Header Section
        label = tk.Label(self.header_frm, text='This is the Main Page')
        label.pack(pady=10, padx=10)

        # footer Section
        close_btn = tk.Button(self.footer_frm, text='Close', command=quit)
        close_btn.grid(row=1, column=1, padx=5, pady=5)

        display_btn = tk.Button(
            self.footer_frm, text='Display', command=self.display)
        display_btn.grid(row=1, column=2, padx=5, pady=5)

        switch_window_btn = tk.Button(
            self.footer_frm, text='Page 2',
            command=lambda: controller.show_frame(controller.page2)
        )
        switch_window_btn.grid(row=1, column=0, padx=5, pady=5)

    def display(self):
        label = tk.Label(
            self.body_frm,
            text='Display method works')
        label.grid(row=2, column=0, columnspan=2, padx=15, pady=5)


class Page2(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text='Second Page')
        label.pack(padx=10, pady=10)

        switch_window_button = tk.Button(
            self,
            text='Return to Page 1',
            command=lambda: controller.show_frame(controller.page1),
        )
        switch_window_button.pack(side='bottom', fill=tk.X)


def main():
    prog_app = App()
    prog_app.mainloop()


if __name__ == '__main__':
    main()

正确的代码

command=lambda: self.frames[self.page1].display()

或者

command=lambda: self.frames[Page1].display()

self.page1不是 class 的实例,而只是Page1的别名。

真实实例在self.frames[self.page1] (或self.frames[Page1]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM