Python Tkinter面向对象 - 以多个框架为中心

时间:2015-12-11 15:43:39

标签: python oop python-3.x tkinter

所以我在Python中编写面向对象的程序,并使用Tkinter构建GUI。我是面向对象和Tkinter的新手,所以我一直在youtube,effbot.org,stackoverflow和zetcode.com上使用Sentdex视频来帮助我。

这是我的计划,我已将其删除了很多,以便更短,更容易理解。它以全屏模式启动并使框架居中。然后我单击登录按钮,然后引发下一帧,但是这一帧不会居中,尽管它位于由权重= 1的单元格包围的网格中间。

list-ref

Login Screen before progress bars are added

当我将以下代码添加到AdminHome类时,问题反转,登录屏幕停止居中但管理员主屏幕变为居中。

import tkinter as tk
from tkinter import ttk

class Program(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(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        container.grid_rowconfigure(2, weight=1)
        container.grid_columnconfigure(2, weight=1)

        self.frames = {}
        frame = Login(container, self)
        self.frames[Login] = frame

        frame.grid(row=1, column=1, sticky="nsew")

        for F in (Login, AdminHome):

            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row = 1, column = 1, sticky = "nsew")

        self.show_frame(Login)

    def show_frame(self,cont):
        frame = self.frames[cont]
        frame.tkraise()

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

        name = tk.Label(self, text = "Program")
        name.grid(row=0, columnspan=5, sticky="W"+"E")

        username = tk.Label(self, text="Username: ")
        username.grid(row=1, columnspan=2, sticky="W")

        user = ttk.Entry(self, text ="", width=45)
        user.grid(row=1, column=2 ,columnspan=3, sticky="w")

        password = tk.Label(self, text="Password: ")
        password.grid(row=2, columnspan=2, sticky="W")

        passentry = ttk.Entry(self, text ="", width=45)
        passentry.grid(row=2, column=2 ,columnspan=3, sticky="W")

        loginb = ttk.Button(self, text = "Login", command = lambda: controller.show_frame(AdminHome))
        loginb.grid(row=3, columnspan=5, sticky="W"+"E")

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

        name = tk.Label(self, text = "Admin Home")
        name.grid(row=0, sticky="W")

        name = tk.Label(self, text = "FirstName + LastName")
        name.grid(row=0, column=5 ,sticky="E")

        update = ttk.Button(self, text = "Update Online", command = lambda: controller.show_frame(AdminHome))
        update.grid(row=1, columnspan=6, sticky="W"+"E")

        fetch = ttk.Button(self, text = "Fetch Data", command = lambda: controller.show_frame(AdminHome))
        fetch.grid(row=2, columnspan=6, sticky="W"+"E")

        a = ttk.Button(self, text = "a", command = lambda: controller.show_frame(AdminHome))
        a.grid(row=3, columnspan=2, sticky="W"+"E")

        b = ttk.Button(self, text = "b", command = lambda: controller.show_frame(AdminHome))
        b.grid(row=3, column=2, columnspan=2, sticky="W"+"E")

        c = ttk.Button(self, text = "c", command = lambda: controller.show_frame(AdminHome))
        c.grid(row=3, column=4, columnspan=2, sticky="W"+"E")

        edit = ttk.Button(self, text = "Edit Details", command = lambda: controller.show_frame(AdminHome))
        edit.grid(row=4, columnspan=6, sticky="W"+"E")

app = Program()
app.state('zoomed')
app.mainloop()

Login Screen after progress bars are added

有人可以告诉我为什么会这样,以及我如何解决它。如果我改变这些框架中小部件的大小以及我添加到程序中的所有其他框架,我还需要解决方案。

1 个答案:

答案 0 :(得分:0)

问题不在于框架不在容器中心,管理页面窗口小部件不在管理框架中居中。通过赋予AdminHome框架独特的颜色,您可以非常轻松地看到这一点。执行此操作时,您会看到AdminHome框架仍然在窗口中居中。

您复制的代码是专为个人"页面"而设计的。对象填充它们所在的单元格。代码只能以这种方式工作,因为小部件全部堆叠在一起。它们需要具有相同的尺寸,否则您将看到较小的框架后面的较大框架。

由于您不太了解代码的工作原理,我的建议是不要尝试更改代码。而不是试图使页面居中,而是专注于使页面中的 页面居中。每个页面都设计为完全独立,因此无论你在该框架内做什么都不会影响任何其他小部件。

让每个页面中的内容居中的最简单的解决方案是使用另一个框架。将所有小部件放在该框架中,然后将该框架居中。你不是真的需要这样做,你也可以使用你之前尝试过的相同技巧,添加"加权"围绕页面内所有小部件的行和列。

以下是一个完整的工作示例。它不是解决问题的唯一方法,甚至可能不是最好的方法。请注意,由于使用了place,您必须为整个窗口提供一个大小(或设置zoomed属性,就像您正在做的那样)。这是因为使用place并不强制窗口适合其内容。

要寻找的重要事项是在每个页面中使用innerFrame。这是集中的事情。

import tkinter as tk
from tkinter import ttk

class Program(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(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (Login, AdminHome):

            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row = 0, column = 0, sticky = "nsew")

        self.show_frame(Login)

    def show_frame(self,cont):
        frame = self.frames[cont]
        frame.tkraise()

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

        innerFrame = tk.Frame(self)
        innerFrame.place(relx=.5, rely=.5, anchor="c")

        name = tk.Label(innerFrame, text = "Program")
        name.grid(row=0, columnspan=5, sticky="W"+"E")

        username = tk.Label(innerFrame, text="Username: ")
        username.grid(row=1, columnspan=2, sticky="W")

        user = ttk.Entry(innerFrame, text ="", width=45)
        user.grid(row=1, column=2 ,columnspan=3, sticky="w")

        password = tk.Label(innerFrame, text="Password: ")
        password.grid(row=2, columnspan=2, sticky="W")

        passentry = ttk.Entry(innerFrame, text ="", width=45)
        passentry.grid(row=2, column=2 ,columnspan=3, sticky="W")

        loginb = ttk.Button(innerFrame, text = "Login", command = lambda: controller.show_frame(AdminHome))
        loginb.grid(row=3, columnspan=5, sticky="W"+"E")

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

        innerFrame = tk.Frame(self)
        innerFrame.place(relx=.5, rely=.5, anchor="c")

        name = tk.Label(innerFrame, text = "Admin Home")
        name.grid(row=0, sticky="W")

        name = tk.Label(innerFrame, text = "FirstName + LastName")
        name.grid(row=0, column=5 ,sticky="E")

        update = ttk.Button(innerFrame, text = "Update Online", command = lambda: controller.show_frame(AdminHome))
        update.grid(row=1, columnspan=6, sticky="W"+"E")

        fetch = ttk.Button(innerFrame, text = "Fetch Data", command = lambda: controller.show_frame(AdminHome))
        fetch.grid(row=2, columnspan=6, sticky="W"+"E")

        a = ttk.Button(innerFrame, text = "a", command = lambda: controller.show_frame(AdminHome))
        a.grid(row=3, columnspan=2, sticky="W"+"E")

        b = ttk.Button(innerFrame, text = "b", command = lambda: controller.show_frame(AdminHome))
        b.grid(row=3, column=2, columnspan=2, sticky="W"+"E")

        c = ttk.Button(innerFrame, text = "c", command = lambda: controller.show_frame(AdminHome))
        c.grid(row=3, column=4, columnspan=2, sticky="W"+"E")

        edit = ttk.Button(innerFrame, text = "Edit Details", command = lambda: controller.show_frame(AdminHome))
        edit.grid(row=4, columnspan=6, sticky="W"+"E")

app = Program()
app.state('zoomed')
app.mainloop()