简体   繁体   English

在 Python 中使用菜单按钮切换帧

[英]Switching frames with Menubutton in Python

I'm trying to make a widget for reports and I'm using menubutton to switch between different frames, but when one frame is closed and open the other - frame is messed up.我正在尝试为报告制作一个小部件,并且我正在使用菜单按钮在不同的框架之间切换,但是当一个框架关闭并打开另一个框架时 - 框架搞砸了。 Here is a code sample:这是一个代码示例:

from tkinter import *
from tkinter import ttk


def window_position(self):
    screen_width = self.master.winfo_screenwidth()
    screen_height = self.master.winfo_screenheight()
    x = (screen_width / 2) - self.width / 2
    y = (screen_height / 2) - self.height / 2
    self.master.geometry('%dx%d+%d+%d' % (self.width, self.height, x, y))


def on_closing(self):
    self.master.destroy()


def closing_window(self):
    self.master.switch_frame(StartPage)


class SampleApp(Tk):
    def __init__(self):
        Tk.__init__(self)
        self._frame = None
        self.switch_frame(StartPage)

    def switch_frame(self, frame_class):
        new_frame = frame_class(self)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.grid(row=0, column=0, sticky='nsew')


class StartPage(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        self.master.title('window')
        self.width = 270
        self.height = 235
        main_color = '#EFFFDE'
        self.config(bg=main_color)

        window_position(self)

        master.protocol("WM_DELETE_WINDOW", lambda: on_closing(self))

        top = Frame(self, relief=GROOVE, bd=2)
        top.grid(row=0, columnspan=4, sticky='ew')

        mb = Menubutton(top, text="Menu", relief=RAISED)
        mb.pack(anchor='nw')
        mb.menu = Menu(mb, tearoff=0)
        mb["menu"] = mb.menu
        mb.menu.config(bd=20)
        mb.menu.add_command(label="Report", command=lambda: master.switch_frame(Report))
        mb.menu.add_command(label="Report 2", command=lambda: master.switch_frame(Report2))


class Report(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        self.master = master
        self.master.title('Report')
        self.width = 210
        self.height = 250

        window_position(self)

        self.master.protocol("WM_DELETE_WINDOW", lambda: closing_window(self))

        label1 = Label(self.master, text='Report 1', font=('Helvetica', 15, 'bold'), height=2)
        label1.grid(row=0, column=0, sticky='n', padx=5)

        top = LabelFrame(self.master, relief=GROOVE, bd=3, text='Type', font=('Helvetica', 10, 'bold', 'italic'),
                         fg='purple')
        top.grid(row=1, column=0, sticky='ew', padx=10, pady=3, ipady=3)
        entry3 = ttk.Combobox(top, values=['1', '2', '3'], justify='center')
        entry3.config(width=15, state='readonly')
        entry3.pack()

        top2 = LabelFrame(self.master, relief=GROOVE, bd=3, text='Month', font=('Helvetica', 10, 'bold', 'italic'),
                          fg='purple')
        top2.grid(row=2, column=0, sticky='ew', padx=10, pady=3, ipady=3)
        entry1 = Entry(top2, width=5)
        entry1.pack()

        top3 = LabelFrame(self.master, relief=GROOVE, bd=3, text='Year', font=('Helvetica', 10, 'bold', 'italic'),
                          fg='purple')
        top3.grid(row=3, column=0, sticky='ew', padx=10, pady=3, ipady=3)
        entry2 = Entry(top3, width=5)
        entry2.pack()

        button = Button(self.master, text="SHOW")
        button.config(font='Helvetica, 8 bold', relief='raised')
        button.grid(row=6, column=0, pady=5, sticky='n')


class Report2(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        self.master = master
        self.master.title('Report 2')
        self.width = 250
        self.height = 250

        window_position(self)

        self.master.protocol("WM_DELETE_WINDOW", lambda: closing_window(self))

        label1 = Label(self.master, text='Report 2', font=('Helvetica', 15, 'bold'), height=2)
        label1.grid(row=0, column=0, sticky='n', padx=5, columnspan=2)

        top = LabelFrame(self.master, relief=GROOVE, bd=3, text='Type', font=('Helvetica', 10, 'bold', 'italic'),
                         fg='purple')
        top.grid(row=1, column=0, sticky='ew', padx=10, pady=3, ipady=3, columnspan=2)

        entry3 = ttk.Combobox(top, values=['1', '2', '3'], justify='center')
        entry3.config(width=15, state='readonly')
        entry3.pack()

        top2 = LabelFrame(self.master, relief=GROOVE, bd=3, text='Parameter', font=('Helvetica', 10, 'bold', 'italic'),
                          fg='purple')
        top2.grid(row=2, column=0, sticky='ew', padx=10, pady=3, ipady=3, columnspan=2)

        entry4 = ttk.Combobox(top2, justify='center')
        entry4.config(width=15, state='readonly')
        entry4.pack()

        top3 = LabelFrame(self.master, relief=GROOVE, bd=3, text='Month', font=('Helvetica', 10, 'bold', 'italic'),
                          fg='purple')
        top3.grid(row=3, column=0, sticky='ew', padx=10, pady=3, ipady=3)

        entry1 = Entry(top3, width=5)
        entry1.pack()

        top4 = LabelFrame(self.master, relief=GROOVE, bd=3, text='Year', font=('Helvetica', 10, 'bold', 'italic'),
                          fg='purple')
        top4.grid(row=3, column=1, sticky='ew', padx=10, pady=3, ipady=3)

        entry2 = Entry(top4, width=5)
        entry2.pack()

        button = Button(self.master, text="SHOW")
        button.config(font='Helvetica, 8 bold', relief='raised', borderwidth=3, bg='#1CD6A9', cursor='hand2')
        button.grid(row=6, column=0, pady=5, sticky='n', columnspan=2)


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

It looks like a frame is overwritten over the previous one.看起来一帧被前一帧覆盖了。 I was trying several solutions but cant get it done.我尝试了几种解决方案,但无法完成。 What I have to change?我必须改变什么?

The problem is that your "pages" don't create widgets inside the page.问题是您的“页面”不会在页面内创建小部件。 For example, consider this line from Report.__init__ :例如,考虑Report.__init__中的这一行:

label1 = Label(self.master, text='Report 1', font=('Helvetica', 15, 'bold'), height=2)

You are creating the label in self.master rather than self .您在self.master而不是self创建 label 。 When you destroy the instance of this class, this label won't get destroyed because it's not a child of self .当您销毁此 class 的实例时,此 label 不会被销毁,因为它不是self的孩子。

If you're going to subclass a frame in order to create widgets, the widgets need to be a child or descendant of the frame.如果您要对框架进行子类化以创建小部件,则小部件需要是框架的子级或后代。

label1 = Label(self, ...)

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

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