【发布时间】:2017-09-10 21:37:09
【问题描述】:
我正在使用最初来自另一个堆栈交换答案的代码构建一个 GUI。我已经修改了它,因为我想将变量传递给后续页面并让它们显示值。作为一种方法,而不是显示在按钮事件上,我正在尝试使用 show() 方法创建页面:
import Tkinter as tk
#import vpnRename12 as Rename
#import vpnRename_pullconfig as pullConfig
"""
Create multiple pages to go through in the same frame. Use lift() to bring
the desired page into view and stack them on top of one another. Define
page-specific methods in each page.
"""
class vpnRenameProgram(tk.Tk):
"""
Create a page class that will allow you to lift to front the applicable
page with the proper functions to keep the script running.
"""
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
# Create an empty dictionary to contain all of the page names
self.frames = {}
self.show("MainView")
# Instantiate the next page on call, rather than at start to allow
flexibility
def instantiate_page(self, cls):
"""
Since all of the pages are defined in the same scope/namespace, we
can use
the globals()[] dict to find and instantiate the pages dynamically
with the show() method.
cls is the class argument we are doing a lookup on in the global()
dict.
"""
try:
newframe = globals()[cls](container,self)
page_name = newframe.__name__
except:
print("\nError defining inline class %s"%cls)#("Class %s is not
defined" %cls)
newframe = None
page_name=globals()[cls].__name__
return newframe, page_name
# Create lift function to bring desired page to front of view,
#instantiate page if
# it isn't already (check frames dict)
def show(self, cls):
if cls not in self.frames.keys():
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
frame, page_name = self.instantiate_page(cls)
if frame==None:
frame = globals()[cls](parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="news")
frame = self.frames[cls]
frame.lift()
def get_page(self, classname):
"""
Return instance of page when it's class name is passed in as string
"""
for page in self.frames.values():
if str(page.__class__.__name__) == classname:
return page
return None
class MainView(tk.Frame):
def __init__(self,parent, controller,**kwargs):
tk.Frame.__init__(self,parent)
self.controller = controller
self.edit_directory="edit_dir"
self.complete_directory ="comp_dir"
TitleLabel = tk.Label(self, text="VPN Script Editor")
TitleLabel.pack({"side":"top"})
EditLabel = tk.Label(self, text="Edit File Directory:
%s"%self.edit_directory)
EditLabel.pack()
CompLabel = tk.Label(self, text="Completed File Directory:
%s"%self.complete_directory)
CompLabel.pack()
Next = tk.Button(self, text="Next", command=lambda:
controller.show("listVPN"))
Next.pack()
class listVPN(tk.Frame):
"""
This is the second page, it contains a text box where you will list the
names of the vpn's that you want to edit. It will also display the
directories
obtained by the pullconfig script.
"""
def read_list(self):
vpn_list=str(self.var_vpn_list.get()).upper()
return vpn_list
def __init__(self, parent, controller, **kwargs):
self.controller = controller
tk.Frame.__init__(self, parent)
self.var_vpn_list = tk.StringVar()
label=tk.Label(self, text="Please list the VPNs desired to edit")
label.pack()
#Create text box to submit a list of vpns back to the main program
vpnLabel = tk.Label(self, text="VPN Names").pack()
self.TextBox = tk.Entry(self, textvariable=self.var_vpn_list)
self.TextBox.pack()
vpnListSubmit = tk.Button(self, text="Enter", command= lambda:
self.read_list() and self.controller.show("pickFiles"))
vpnListSubmit.pack()
class pickFiles(tk.Frame):
"""
Second page that allows you to select your desired files from the
edit directory specified in the config file. Check all desired files,
list will be returned to the program.
"""
def get_vpn_list(self):
list = self.controller.get_page("listVPN").var_vpn_list.get()
self.vpn_list = str(list).upper()
self.vpn_label.configure(text="VPN List: %s"%self.vpn_list)
return self.vpn_list
def __init__(self, parent, controller,**kwargs):
# Inherits from the tk.Frame class
tk.Frame.__init__(self, parent)
self.controller = controller
self.vpn_list = tk.StringVar()
list = self.controller.get_page("listVPN").var_vpn_list.get()
self.vpn_list = str(list).upper()
show_vpn = tk.Button(self, text="Show vpnlist", command =
self.get_vpn_list)
show_vpn.pack()
self.vpn_label = tk.Label(self, text="VPN List: %s" %self.vpn_list)
self.vpn_label.pack()
# todo: get external module function to run with variable input
#file_list = Rename.searchFile(vpnlist)
# Execute program on calling the parent class
if __name__=="__main__":
app = vpnRenameProgram()
app.mainloop()
编辑: 以上是我导入的自定义脚本的整个代码注释掉了。我的主要问题是关于布局。我希望框架相互堆叠,但事实并非如此。为什么要这样做?什么能让我走上获得我想要的布局的轨道?
【问题讨论】:
-
我很困惑你想要什么。您能否提供一个我们可以运行的完整示例来说明您遇到的问题?
-
“我已经修改了它,因为我想将变量传递给后续页面” - 你为什么这样做?您从中复制的代码使得在页面之间共享公共数据块或让每个页面从任何其他页面获取它想要的数据变得非常简单。创建页面时无需向页面传递数据。
-
这句话很难理解:“我希望每个页面只使用一个容器实例,因为这会导致每个页面单独分层。” 每个页面正在使用容器的一个实例。你不需要改变任何东西。另外,您写了 “我不希望容器成为全局变量”,但
container不是全局变量。它是传递给每个页面的局部变量。 -
您是否阅读了以下问题和答案? stackoverflow.com/questions/32212408/… 和 stackoverflow.com/questions/33646605/…?您能解释一下为什么这些页面都不能解决您的问题吗?
-
这似乎是XY problem。也许与其试图让我们修复您损坏的代码,不如解释一下您要解决的真正问题。
标签: python-2.7 oop user-interface tkinter