我有一个gui应用程序,其中导航栏具有在帧之间切换的按钮。在起始页上,有一个输入小部件以获取文件名,以及一个列表框以显示所有保存的文件名。从列表框中选择文件名后,会打开另一个页面,其中显示所选文件名。
我相信答案here在开头会创建框架对象,将其堆叠并抬高被调用的框架。但是我认为我的窗口每次被调用时都需要更新,以便它可以显示不同的文件名。而且它与其他框架放置在完全相同的位置,因此我仍然可以使用导航栏按钮切换到其他家庭和其他窗口。我发现与此here类似,但我听不懂。
(我的主要申请程序比这要复杂一些,但我认为这只是我的问题的小而精确的表示)
修改:
import tkinter as tk
class MainApplication(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(1, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames={}
for F in (StartPage,PageOne):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=1, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
self.list_box = tk.Listbox(self)
self.list_box.pack()
for item in ["file 1", "file 2", "file 3"]:
self.list_box.insert(tk.END, item)
button1 = tk.Button(self, text='Go to next Page', command=lambda: self.getvalue(controller))
button1.pack()
def getvalue(self, controller):
clicked_item=self.list_box.curselection()
selected_file=self.list_box.get(clicked_item)
print(selected_file)
controller.show_frame('PageOne')
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# ....selected file name to be displayed here....
button1 = tk.Button(self, text="Back to Home", command=lambda: controller.show_frame('StartPage'))
button1.pack()
app = MainApplication()
app.geometry("400x400")
app.mainloop()
答案 0 :(得分:2)
问题:每次我想从PageOne
转到StartPage
时如何传递selected_file名称。
核心点:
重载类方法Frame.tkraise
以在PageOne
的每次调用.tkraise
时更新controller
小部件
注意:我只显示示例代码的更改部分,仔细比较并复制到您的真实代码。
class MainApplication(tk.Tk):
class MainApplication(tk.Tk):
...
class StartPage(tk.Frame):
class StartPage(tk.Frame):
def __init__(self, parent, controller):
...
.Button(..., command=lambda: controller.show_frame('PageOne'))
def getvalue(self):
...
return selected_file
class PageOne(tk.Frame):
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
# ....selected file name to be displayed here....
self.label = tk.Label(self, text='')
self.label.pack()
def tkraise(self, aboveThis=None):
# Get a reference to StartPage
start_page = self.controller.frames['StartPage']
# Get the selected item from start_page
self.label.configure(text=start_page.getvalue())
# Call the real .tkraise
super().tkraise(aboveThis)
替代:
答案 1 :(得分:1)
#Multiple Screens
from tkinter import *
class screen(Frame):
"""
A screen is area
for content in a program
"""
def __init__(self,master,name):
Frame.__init__(self,master)
#Attributes
self.master=master
self.name=name
#Initalise with master
self.master.addScreen(self)
def show(self):
"""
Method will show screen
"""
self.master.showScreen(self.name)
class screenController(Frame):
"""
Screen Controller
will manage screens
in the program
"""
def __init__(self,parent):
Frame.__init__(self,parent)
#Configure
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
#Attributes
self.allScreens={}
self.currentScreen=None
def addScreen(self,screenObject):
"""
Adds a Screen object to the screenController
"""
#Place the screen
screenObject.grid(row=0, column=0, sticky="nsew")
#Add to dictionary
self.allScreens[screenObject.name]=screenObject
def showScreen(self,screenName):
if screenName in self.allScreens:
#Display
self.allScreens[screenName].tkraise()
#Update variable
self.currentScreen=screenName
#Create a Tkinter Window
window=Tk()
window.title("Multiple Screens")
window.geometry("400x300")
window.columnconfigure(0,weight=1)
window.rowconfigure(1,weight=1)
#Create a Controller for the screens
screenMaster=screenController(window)
screenMaster.grid(row=1,column=0,sticky="NSEW")
#Create SCREEN 1
screen1=screen(screenMaster, "S1")
Label(screen1,text="This is screen 1").grid(row=0,column=0)
screen1.config(bg="red")
#Create SCREEN 2
screen2=screen(screenMaster, "S2")
Label(screen2,text="This is screen 2").grid(row=0,column=0)
screen2.config(bg="blue")
#Create SCREEN 3
screen3=screen(screenMaster, "S3")
Label(screen3,text="This is screen 3").grid(row=0,column=0)
screen3.config(bg="green")
#Create a navigation bar
navBar=Frame(window)
navBar.grid(row=0,column=0,sticky="EW")
navBar.config(bg="#F1F0F2")
b1=Button(navBar,text="Screen 1",command=lambda: screen1.show())
b1.grid(row=0,column=0)
b1=Button(navBar,text="Screen 2",command=lambda: screen2.show())
b1.grid(row=0,column=1)
b1=Button(navBar,text="Screen 3",command=lambda: screen3.show())
b1.grid(row=0,column=2)
#Show screen 1 by default
screen1.show()
window.mainloop()
这是我使用OO编程解决此问题的方式,无论您在哪个“屏幕”上,导航栏都将保持静态,而只需将屏幕彼此抬高即可,无需继续创建新对象并节省大量内存。
此解决方案也是非常模块化的,仅允许您添加屏幕,就好像它们是Tkinter框架一样。