从多个帧切换时无法使tkinter帧居中

时间:2019-11-19 10:12:35

标签: python python-3.x tkinter

我对tkinter相当陌生,我使用的是这篇帖子顶部评论中的代码:Switch between two frames in tkinter,并进行了一些更改,以便能够在两个框架之间切换。问题是当我为此添加第二个框架或其他不是第一个框架时,我无法将其居中。如果我说我仍然很了解tkinter和python,而我并没有真正理解这篇文章中的代码是如何工作的,我对此表示歉意。这是我的代码:


import tkinter as tk              

class MainView(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)


        container = tk.Frame(self)
        container.pack(expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        self.frames["LoginFrame"] = LoginFrame(parent=container, controller=self)
        self.frames["RegisterFrame"] = RegisterFrame(parent=container, controller=self)

        self.frames["LoginFrame"].grid(row=0, column=0, sticky="NESW")
        self.frames["RegisterFrame"].grid(row=0, column=0, sticky="NESW")


        self.ShowFrame("LoginFrame")

    def ShowFrame(self, PageName):
        frame = self.frames[PageName]
        frame.tkraise()


class LoginFrame(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        WelcomeLabel = tk.Label(self, text="Welcome to Detention Organiser!",font=(None,20) ).grid(columnspan=2)
        UsernameLabel = tk.Label(self, text="Username",font=(None,15) ).grid(row=1, sticky="E")
        PasswordLabel = tk.Label(self, text="Password",font=(None,15) ).grid(row=2, sticky="E")

        UsernameEntry  = tk.Entry(self).grid(row=1, column=1, sticky="W")
        PasswordEntry = tk.Entry(self, show="*").grid(row=2, column=1, sticky="W")

        LoginButton = tk.Button(self, text="Login").grid(columnspan=2)
        RegisterButton = tk.Button(self, text="Sign Up",command=lambda: controller.ShowFrame("RegisterFrame")).grid(columnspan=2)



class RegisterFrame(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        self.Variable = tk.StringVar()
        self.Variable.set("7A")

        RegisterLabel = tk.Label(self, text="Register",font=(None,20)).grid(columnspan=2)
        UsernameLabel = tk.Label(self, text="Username",font=(None,15)).grid(row=1, sticky="E")
        PasswordLabel = tk.Label(self, text="Password",font=(None,15)).grid(row=2, sticky="E")
        FormGroupLabel = tk.Label(self, text="Form Group",font=(None,15) ).grid(row=3, sticky="E")

        UsernameEntry  = tk.Entry(self).grid(row=1, column=1, sticky="W")
        PasswordEntry = tk.Entry(self, show="*").grid(row=2, column=1, sticky="W")
        FormGroupDrop  = tk.OptionMenu(self,self.Variable,"7A","7B","8A","8B").grid(row=3, column=1, sticky="W")

        RegisterButton = tk.Button(self, text="Register",command=lambda: controller.ShowFrame("RegisterFrame"))
        RegisterButton.grid(columnspan=2)
        BackButton = tk.Button(self, text="Back",command=lambda: controller.ShowFrame("LoginFrame")).grid(columnspan=2)



if __name__ == "__main__":
    app = MainView()
    app.geometry("640x360")
    app.mainloop()

1 个答案:

答案 0 :(得分:0)

第一件事,通常是在程序中,避免做类似的事情:

UsernameEntry  = tk.Entry(self).grid(row=1, column=1, sticky="W")

因为变量UsernameEntry并非您所期望的tk.Entry,因此有时肯定会导致错误。而是使用以下之一:

# If you need the variable later
UsernameEntry  = tk.Entry(self)
UsernameEntry.grid(row=1, column=1, sticky="W")

# Otherwise
tk.Entry(self).grid(row=1, column=1, sticky="W")

现在,回到您的问题。缺少的是您不知道程序应如何分配剩余空间(不需要空间来包含窗口小部件)。默认情况下,网格会将您的小部件放置在尽可能靠近容器顶部/左侧的位置。要更改此行为,您将需要使用grid_columnconfigure和/或grid_rowconfigure。例如,

self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1)

告诉程序剩余空间应在列0和列1之间平均分配。权重可以是任何非负整数值:

self.grid_columnconfigure(0, weight=3)
self.grid_columnconfigure(1, weight=0)
self.grid_columnconfigure(2, weight=1)

这告诉程序将剩余空间的3/4分配给第0列,将None分配给第1列,将1/4分配给第2列。默认情况下,所有权重均为0。

然后,您的课程LoginFrameRegisterFrame可能看起来像

class LoginFrame(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        self.grid_rowconfigure(5, weight=1) # Fills vertical space below the last row
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=1)

        tk.Label(self, text="Welcome to Detention Organiser!",font=(None,20) ).grid(columnspan=2)
        tk.Label(self, text="Username",font=(None,15)).grid(row=1, sticky="E")
        tk.Label(self, text="Password",font=(None,15)).grid(row=2, sticky="E")

        tk.Entry(self).grid(row=1, column=1, sticky="W")
        tk.Entry(self, show="*").grid(row=2, column=1, sticky="W")

        tk.Button(self, text="Login").grid(row=3, columnspan=2)
        tk.Button(self, text="Sign Up",command=lambda: controller.ShowFrame("RegisterFrame")).grid(row=4, columnspan=2)


class RegisterFrame(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        self.Variable = tk.StringVar()
        self.Variable.set("7A")

        self.grid_rowconfigure(5, weight=1) # Fills vertical space below the last row
        self.grid_columnconfigure(0, weight=0)
        self.grid_columnconfigure(1, weight=1)

        tk.Label(self, text="Register",font=(None,20)).grid(columnspan=2)
        tk.Label(self, text="Username",font=(None,15)).grid(row=1, sticky="E")
        tk.Label(self, text="Password",font=(None,15)).grid(row=2, sticky="E")
        tk.Label(self, text="Form Group",font=(None,15) ).grid(row=3, sticky="E")

        tk.Entry(self).grid(row=1, column=1, sticky="W")
        tk.Entry(self, show="*").grid(row=2, column=1, sticky="W")
        tk.OptionMenu(self,self.Variable,"7A","7B","8A","8B").grid(row=3, column=1, sticky="W")

        RegisterButton = tk.Button(self, text="Register",command=lambda: controller.ShowFrame("RegisterFrame"))
        RegisterButton.grid(columnspan=2)
        tk.Button(self, text="Back",command=lambda: controller.ShowFrame("LoginFrame")).grid(columnspan=2)

最后,tkinter有许多不同的选项,您需要进行测试才能真正了解它们的工作原理。在进行一些测试时,建议您广泛使用选项bg="COLOR",该选项将更改窗口小部件的背景并准确告诉您其边界。例如,

        tk.Frame.__init__(self, parent, bg="RED")