在 Python 中使用 Menubutton 切换框架
Switching frames with Menubutton in Python
我正在尝试为报告制作一个小部件,我正在使用菜单按钮在不同的框架之间切换,但是当一个框架关闭并打开另一个框架时,框架就乱七八糟了。这是一个代码示例:
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()
看起来一帧覆盖了前一帧。我正在尝试几种解决方案,但无法完成。我必须改变什么?
问题是您的“页面”没有在页面内创建小部件。例如,考虑来自 Report.__init__
:
的这一行
label1 = Label(self.master, text='Report 1', font=('Helvetica', 15, 'bold'), height=2)
您正在 self.master
而不是 self
中创建标签。当您销毁此 class 的实例时,此标签不会被销毁,因为它不是 self
.
的子项
如果您要子class 框架以创建小部件,小部件需要是框架的子项或后代。
label1 = Label(self, ...)
我正在尝试为报告制作一个小部件,我正在使用菜单按钮在不同的框架之间切换,但是当一个框架关闭并打开另一个框架时,框架就乱七八糟了。这是一个代码示例:
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()
看起来一帧覆盖了前一帧。我正在尝试几种解决方案,但无法完成。我必须改变什么?
问题是您的“页面”没有在页面内创建小部件。例如,考虑来自 Report.__init__
:
label1 = Label(self.master, text='Report 1', font=('Helvetica', 15, 'bold'), height=2)
您正在 self.master
而不是 self
中创建标签。当您销毁此 class 的实例时,此标签不会被销毁,因为它不是 self
.
如果您要子class 框架以创建小部件,小部件需要是框架的子项或后代。
label1 = Label(self, ...)