如何在tkinter gui

问题描述

我正处于制作GUI的初期。现在,我具有登录视图(LogInWind类)和注册视图(SignUpWind类)。当我只有一个视图时,一切都很好,但是现在我对这两个对象有了循环依赖。这是通过按钮的命令发生的,因为在登录视图中有一个按钮可将您带到注册视图,反之亦然。我想我可以为注册视图创建一个弹出窗口。但是,我认为切换窗口的方式是一种不好的做法,以后可能会带来更大的问题。

我的项目结构如下。

enter image description here

服务包将在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"))

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...