tkinter:使用相同的框架,但有不同的命令按钮?



请原谅我的错误语法或解释,因为我不知道如何正确解释。

我尝试构建一些可以在帧之间切换的gui,使用此脚本作为tkinter中两个帧之间切换的基础。

在这种情况下,我将有几个框架具有类似的设计,但不同的功能,当按钮被按下。例如,我有两个帧,它们有相似的两个条目和一个按钮,但按钮执行不同的命令(其中在sub01帧它将相乘,在sub02帧将除法)

这是我的代码:

class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.grid(row=1,columnspan=4,sticky='nsew')
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (sub01, sub02):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=1,sticky="nsew")

self.choices = {'sub01','sub02'}
self.tkvar = tk.StringVar()
self.tkvar.set('sub01')
self.popMenu = tk.OptionMenu(self,self.tkvar,*self.choices)
self.popMenu.grid(row=0)
self.show_frame()
self.button1 = tk.Button(self, text="Go to Layer",command=lambda: self.show_frame())
self.button1.grid(row=0, column=1)
def show_frame(self):
'''Show a frame for the given page name'''
page_name = self.tkvar.get()
frame = self.frames[page_name]
frame.tkraise()
class sub01(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This SubLayer 1")
label.grid(row=0)
self.entries=[]
i = 0
while i < 2:
self.entries.append(tk.Entry(self,width=10))
self.entries[i].grid(row=i+1,columnspan=2,sticky='we')
i += 1
self.btn = tk.Button(self,text="multiply", command=lambda : self.multiply())
self.btn.grid(row=i+1, columnspan=2,sticky='we')
def multiply(self):
pass
class sub02(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This SubLayer 2")
label.grid(row=0)
self.entries=[]
i = 0
while i < 2:
self.entries.append(tk.Entry(self,width=10))
self.entries[i].grid(row=i+1,columnspan=2,sticky='w')
i += 1
self.btn = tk.Button(self,text="divide",command=lambda : self.divide())
self.btn.grid(row=i+1, columnspan=2,sticky='we')
def divide(self):
pass
if __name__ == "__main__":
app = SampleApp()
app.mainloop()

这段代码本身可以工作,但是当我需要创建更多这样的帧时,它就变得不方便了。我怎样才能使这段代码更简单?就像把类似的框架作为一个类,把按钮作为其他类,根据所显示的层有不同的行为。

提前谢谢你

做这类事情的规范方法是为您的Page类创建一个类层次结构,并将公共功能放在基类中,并从中派生子类,这些子类指定它们之间的不同行为。下面是如何使用问题中的示例代码来实现这一点。

因为它们之间的不同之处是:

  1. Label.
  2. 显示文本。
  3. Button上显示的文本。
  4. 点击Button时执行的代码。

这意味着派生类只需要知道在一个通用命名的btn_func()方法中运行什么代码,以及在两个小部件上显示什么文本。下面的代码说明了如何做到这一点。

请注意,我已经更改了类名的拼写,以符合PEP 8 - Python代码风格指南中描述的命名约定。

import Tkinter as tk

class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.grid(row=1,columnspan=4,sticky='nsew')
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (Sub01, Sub02):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=1,sticky="nsew")
self.choices = {'Sub01','Sub02'}
self.tkvar = tk.StringVar()
self.tkvar.set('Sub01')
self.popMenu = tk.OptionMenu(self,self.tkvar,*self.choices)
self.popMenu.grid(row=0)
self.show_frame()
self.button1 = tk.Button(self, text="Go to Layer",command=lambda: self.show_frame())
self.button1.grid(row=0, column=1)
def show_frame(self):
'''Show a frame for the given page name'''
page_name = self.tkvar.get()
frame = self.frames[page_name]
frame.tkraise()

class BaseSubLayer(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text=self.lbl_text)
label.grid(row=0)
self.entries=[]
i = 0
while i < 2:
self.entries.append(tk.Entry(self,width=10))
self.entries[i].grid(row=i+1,columnspan=2,sticky='we')
i += 1
self.btn = tk.Button(self,text=self.btn_func_name, command=self.btn_func)
self.btn.grid(row=i+1, columnspan=2,sticky='we')
def btn_func(self):
raise NotImplementedError

class Sub01(BaseSubLayer):
lbl_text = 'This SubLayer 1'
btn_func_name = 'multiply'
def btn_func(self):
print('Running multiply() method.')

class Sub02(BaseSubLayer):
lbl_text = 'This SubLayer 2'
btn_func_name = 'divide'
def btn_func(self):
print('Running divide() method.')

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

最新更新