问题描述
我正处于制作GUI的初期。现在,我具有登录视图(LogInWind
类)和注册视图(SignUpWind
类)。当我只有一个视图时,一切都很好,但是现在我对这两个对象有了循环依赖。这是通过按钮的命令发生的,因为在登录视图中有一个按钮可将您带到注册视图,反之亦然。我想我可以为注册视图创建一个弹出窗口。但是,我认为切换窗口的方式是一种不好的做法,以后可能会带来更大的问题。
我的项目结构如下。
服务包将在gui和数据库之间建立连接。目前,它什么也没做。
我很高兴获得所有反馈。如果需要进一步的解释,我很乐意这样做。
root.py
import tkinter as tk
from .log_in_window import LogInWind as LIWind
from .sign_up_window import SignUpWind as SuWind
from services.messenger import Messenger
class Root(tk.Tk):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
# General variables.
self.frames = {}
self.width_window
self.height_window
self.container = tk.Frame(self,relief="groove")
# General app configurations.
self.title("SECOM")
self.iconbitmap("C:/Users/joshu/Documents/VSC/python/secom/icons/icon.ico")
self.configure(bg="#E0E0E0")
# Container setup.
self.container.pack(side="top",fill="both",expand=True)
self.container.grid_rowconfigure(0,weight=1)
self.container.grid_columnconfigure(0,weight=1)
def createFrame(self,page_name):
"""
INPUT: view object.
OUTPUT: None
Description: creates frame for the view `page_name`.
"""
# Setup `newFrame.`
newFrame = page_name(parent=self.container,controller=self)
newFrame.configure(bg="#E0E0E0")
newFrame.grid(row=0,column=0,sticky=tk.NSEW)
# Add `newFrame` to catalog of frames.
self.__frames[page_name] = newFrame
def showFrame(self,page_name):
"""
INPUT: view object.
OUTPUT: None.
Calls the view `page_name` up front for display.
"""
try:
# Bings requested view to the front.
self.frames[page_name].tkraise()
except KeyError:
# Creates view and displays it.
self.createFrame(page_name)
self.frames[page_name].tkraise()
def setLocation(self):
"""
INPUT: None
OUTPUT: None
Description: Sets window in the middle of the screen.
"""
self.widthWindow = 400
self.heightwindow = 225
widthScreen = self.winfo_screenwidth()
hightScreen = self.winfo_screenheight()
x = (widthScreen / 2) - (self.widthWindow / 2)
y = (hightScreen / 2) - (self.heightwindow / 2)
self.geometry("%dx%d+%d+%d" % (self.widthWindow,self.heightwindow,x,y))
log_in_window.py
import tkinter as tk
import tkinter.font as tkf
from .sign_up_window import SignUpWind as SUWind # <-- circular dependency
class LogInWind(tk.Frame):
def __init__(self,parent,controller):
super().__init__(parent,controller)
# Creation of labels.
self.titleLbl = tk.Label(self,text="Iniciar Secion",font=tkf.Font(family="Helvetica",size=15,weight="bold"),bg="#E0E0E0")
self.userLbl = tk.Label(self,text="Usuario:",size=10,bg="#E0E0E0")
self.pswdLbl = tk.Label(self,text="Contraseña:",bg="#E0E0E0")
# Creation of entries.
self.userEty = tk.Entry(self)
self.pswdEty = tk.Entry(self,show="*")
# Creation of buttons.
self.logInBtn = tk.Button(self,width=15,text="Iniciar Sesion",bg="#0080FF",################################### ADD COMMAND
fg="#fff")
self.signUpBtn = tk.Button(self,text="Crear cuenta",command=lambda: controller.showFrame(SUWind),# <---- use object HERE.
fg="#fff")
# Places labels.
self.titleLbl.grid(row=0,padx=400 / 2 - 60,pady=10,sticky=tk.SW)
self.userLbl.grid(row=1,padx=parent.width_window / 2 - 60,sticky=tk.SW)
self.pswdLbl.grid(row=3,sticky=tk.W)
# Places entries (string inputs).
self.userEty.grid(row=2,pady=5)
self.pswdEty.grid(row=4,pady=5)
# # Places buttons
self.logInBtn.grid(row=5,sticky=tk.N)
self.signUpBtn.grid(row=6,sticky=tk.S,pady=10)
sing_up_window.py
import tkinter as tk
import tkinter.font as tkf
from .log_in_window import LogInWind as LIWind # <-- circular dependency
class SignUpWind(tk.Frame):
def __init__(self,controller):
super().__init__(parent,controller)
# Setup imge for back button.
self.img = tk.PhotoImage(file="C:/Users/joshu/Documents/VSC/python/secom/icons/return.png")
self.img = self.img.subsample(4,4)
# Create label.
self.titleLbl = tk.Label(self,text="Crear cuenta nueva",bg="#E0E0E0")
self.pswdConfirmlbl = tk.Label(self,text="Cormirma Contraseña:",bg="#E0E0E0")
# Creation of entries.
self.userEty = tk.Entry(self)
self.pswdEty = tk.Entry(self,show="*")
self.pswdConfirmEty = tk.Entry(self,show="*")
# Creation of button.
self.backBtn = tk.Button(self,image=self.img,command=lambda: controller.showFrame(LIWind)) <----- use object HERE.
self.CreateBtn = tk.Button(self,width=8,text="Crear",############################ ADD COMAND
fg="#fff")
# Places labels.
self.titleLbl.grid(row=0,padx=400 / 2 - 90,sticky=tk.W)
self.pswdLbl.grid(row=3,sticky=tk.W)
self.pswdConfirmlbl.grid(row=5,pady=5,sticky=tk.W)
self.pswdEty.grid(row=4,sticky=tk.W)
self.pswdConfirmEty.grid(row=6,sticky=tk.W)
# Places buttons
self.backBtn.grid(row=0,sticky=tk.W)
self.CreateBtn.grid(row=7,padx=100,sticky=tk.N)
主要 .py
from views.root import Root
from views.log_in_window import LogInWind as LIWind
if __name__ == '__main__':
root = Root()
root.showFrame(LIWind)
root.mainloop()
解决方法
如果您设计代码以使页面名称作为字符串而不是作为类传递,那么就不会出现此问题。
例如,在root.py中,您可以从以下内容开始:
pages = {
"log in": LIWind,"sign up": SuWind,}
接下来,在createFrame
中,您将执行以下操作:
def createFrame(self,page_name):
...
cls = pages[page_name]
newFrame = cls(parent=self.container,controller=self)
...
self.__frames[page_name] = newFrame
然后,在需要窗口的任何地方都可以输入页面名称,例如:
self.backBtn = tk.Button(...,command=lambda: controller.showFrame("log in"))