[英]Tkinter Class structure (class per frame) issue with duplicating widgets
我一直在尝试将OOP与Tkinter一起使用-我正在慢慢到达那里(我认为)...
我想构建一个结构,其中每个框架都由其自己的类处理,包括其所有小部件和功能。 也许我是从错误的角度出发的,但这对我来说是最合乎逻辑的。 -随时告诉我您是否同意!
我知道为什么会发生问题-当我调用每个类时,我的__init__
每次都会运行并构建相关的小部件,无论它们是否已存在于框架中。 但是,我能想到的唯一方法是在主类GUI_Start
的__init__
中构建每个框架。 -尽管这看起来像是一个杂乱无章的解决方案。
有没有办法实现一种结构,使每个类都负责自己的功能和小部件,但不必每次都构建框架?
请参阅以下问题的最小示例:
from Tkinter import *
class GUI_Start:
def __init__(self, master):
self.master = master
self.master.geometry('300x300')
self.master.grid_rowconfigure(0, weight=1)
self.master.grid_columnconfigure(0, weight=1)
self.win_colour = '#D2B48C'
self.frames = {}
for window in ['win1', 'win2']:
frame = Frame(self.master, bg=self.win_colour, bd=10, relief=GROOVE)
frame.grid(row=0, column=0, sticky='news')
setattr(self, window, frame)
self.frames[window] = frame
Page_1(self.frames)
def Next_Page(self, frames, controller):
controller(frames)
class Page_1(GUI_Start):
def __init__(self, master):
self.master = master
self.master['win1'].tkraise()
page1_label = Label(self.master['win1'], text='PAGE 1')
page1_label.pack(fill=X)
page1_button = Button(self.master['win1'], text='Visit Page 2...', command=lambda: self.Next_Page(self.master, Page_2))
page1_button.pack(fill=X, side=BOTTOM)
class Page_2(GUI_Start):
def __init__(self, master):
self.master = master
self.master['win2'].tkraise()
page2_label = Label(self.master['win2'], text='PAGE 2')
page2_label.pack(fill=X)
page2_button = Button(self.master['win2'], text='Back to Page 1...', command=lambda: self.Next_Page(self.master, Page_1))
page2_button.pack(fill=X, side=BOTTOM)
root = Tk()
gui = GUI_Start(root)
root.mainloop()
随意批评结构,因为我可能尝试从错误的角度进行研究!
任何反馈将不胜感激! 路加
使用类的重点是将一堆行为封装为一个单元。 对象不应该修改自身之外的任何内容。 至少,不是通过简单地创建对象,而是可以使用具有副作用的方法。
我认为,创建“页面”的正确方法是从Frame
继承。 属于“页面”的所有小部件都必须具有对象本身作为其父对象。 例如:
class PageOne(tk.Frame):
def __init__(self, parent):
# use the __init__ of the superclass to create the actual frame
tk.Frame.__init__(self, parent)
# all other widgets use self (or some descendant of self)
# as their parent
self.label = tk.Label(self, ...)
self.button = tk.Button(self, ...)
...
完成后,可以将此类的实例视为单个窗口小部件:
root = tk.Tk()
page1 = PageOne(root)
page1.pack(fill="both", expand=True)
如果您的所有页面都有共同点(例如,页眉或页脚),您还可以创建一个基类Page
,并让您的实际页面继承自该类。
class Page(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
<code common to all pages goes here>
class PageOne(Page):
def __init__(self, parent):
# initialize the parent class
Page.__init__(self, parent)
<code unique to page one goes here>
您在这里对OOP的使用不是很合逻辑。 您的主程序在GUI_start类中。 如果您的页面是从GUI_start继承的,则基本上您会使用创建的每个页面实例创建一个全新的程序。 您应该改从Frame继承,因为Bryan Oakley在评论中指出了我们的观点。 这是您所发布内容的某种修复版本。 布莱恩(Bryan)创作的第一张仍然更好。
from Tkinter import *
class GUI_Start:
def __init__(self, master):
self.master = master
self.master.geometry('300x300')
self.master.grid_rowconfigure(0, weight=1)
self.master.grid_columnconfigure(0, weight=1)
self.win_colour = '#D2B48C'
self.current_page=0
self.pages = []
for i in range(5):
page = Page(self.master,i+1)
page.grid(row=0,column=0,sticky='nsew')
self.pages.append(page)
for i in range(2):
page = Page_diff(self.master,i+1)
page.grid(row=0,column=0,sticky='nsew')
self.pages.append(page)
self.pages[0].tkraise()
def Next_Page():
next_page_index = self.current_page+1
if next_page_index >= len(self.pages):
next_page_index = 0
print(next_page_index)
self.pages[next_page_index].tkraise()
self.current_page = next_page_index
page1_button = Button(self.master, text='Visit next Page',command = Next_Page)
page1_button.grid(row=1,column=0)
class Page(Frame):
def __init__(self,master,number):
super().__init__(master,bg='#D2B48C')
self.master = master
self.master.tkraise()
page1_label = Label(self, text='PAGE '+str(number))
page1_label.pack(fill=X,expand=True)
class Page_diff(Frame):
def __init__(self,master,number):
super().__init__(master)
self.master = master
self.master.tkraise()
page1_label = Label(self, text='I am different PAGE '+str(number))
page1_label.pack(fill=X)
root = Tk()
gui = GUI_Start(root)
root.mainloop()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.