簡體   English   中英

一幀上的tkinter小部件影響另一幀對齊

[英]tkinter widgets on one frame affecting another frame alignment

到目前為止,該程序在功能上都是明智的,所以這不是我的問題。 我的問題與多幀小部件的對齊方式如何有關。 如果我將小部件在寬度上比其他框架長一幀,它將基於最寬的框架而不是每個單獨的框架將所有框架居中。 此代碼中目前最寬的框架是“ ChangePasswordPage”,因為它幾乎總是使用長字符串作為標簽; 這會使所有其他框向左移動。 如果我從frame.grid(column = 0,row = 0,sticky =“ nsew”)中刪除'sticky =“ nsew”',它將正確地對齊所有內容,但該框架不會向外填充,因此您可以看到其他框架彼此落后。

我不確定如何解決此問題,希望獲得幫助。 我一直在嘗試不同的方式,例如卸載每個小部件,然后重新加載它,但在那里也出現錯誤。 任何幫助將不勝感激。

這是我的壓縮代碼:

import tkinter as tk
from tkinter import ttk, messagebox

class CCTV(tk.Tk):

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

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

        self.frames = {}

        for F in (LoginPage, ChangePasswordPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(column=0, row=0, sticky="nsew")

        self.creatingAccount()

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

    def creatingAccount(self):
        self.show_frame(LoginPage)



class LoginPage(tk.Frame):

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

    def createView(self):
        self.labelPassword = ttk.Label(self, text="Password")
        self.entryPassword = ttk.Entry(self, show = "*")
        self.buttonLogin = ttk.Button(self, text="Login", command=lambda: self.controller.show_frame(ChangePasswordPage))

        self.labelPassword.grid(row=2, column=3, sticky="w")
        self.entryPassword.grid(row=2, column=4, sticky="e")
        self.buttonLogin.grid(row=3, columnspan=6, pady=10)


class ChangePasswordPage(tk.Frame):

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

    def createView(self):
        self.labelSecurityQuestion = ttk.Label(self, text="A very very very very very very very very very very long string")
        self.entrySecurityQuestion = ttk.Entry(self)
        self.buttonCreateAccount = ttk.Button(self, text="Change Password", command=lambda: self.controller.show_frame(LoginPage))

        self.labelSecurityQuestion.grid(row=3, column=0, sticky="w")
        self.entrySecurityQuestion.grid(row=3, column=1, sticky="e")
        self.buttonCreateAccount.grid(row=5, columnspan=2, pady=10)


app = CCTV()
app.geometry("800x600")
app.mainloop()

通常有很多方法可以解決布局問題。 這完全取決於您實際想要做的事情,正在使用的實際小部件以及當它們的包含的窗口或框架發生更改時您期望小部件如何反應。

當您使用grid ,默認情況下,它僅為小部件提供所需的空間。 包含的窗口小部件內的任何多余空間將不使用。 如果要讓grid使用所有可用空間,則必須通過賦予行和列“權重”來告訴它如何分配額外的空間。 您沒有這樣做,所以沒有使用額外的空間,因此,您的小部件沒有居中。

根據經驗,對於使用網格的任何容器(通常是框架),必須至少對一行和一列賦予權重。 如果您有畫布或文本小部件,通常它所在的行和列就是您要獲得未分配空間的空間。 如果您有想要增加和縮小的條目窗口小部件,則通常會對包含條目窗口小部件的列進行加權。 通常,您會想為多行和/或多列分配額外的空間,盡管有時也需要將所有內容居中,並沿邊緣分配額外的空間。

在您的特定情況下,要將所有內容放在密碼屏幕的中央,有幾種解決方案。 我會詳細介紹幾個。

僅使用網格,並將所有小部件直接放置在頁面上

如果您想將所有小部件絕對排列在一個框架中,並使用grid管理,並且希望所有內容都集中在窗口中,則可以將所有權重賦予圍繞內容的行和列。

這是一個例子。 請注意,小部件位於第1和2行,第1和2列,並且所有額外的空間都分配給第0和3行以及第0和3列。

def createView(self):
    ...
    self.labelPassword.grid(row=1, column=1, sticky="e")
    self.entryPassword.grid(row=1, column=2, sticky="ew")
    self.buttonLogin.grid(row=2, column=1, columnspan=2)

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

使用嵌套框架

另一種方法是將小部件放置在完全適合其內容的內部框架中。 這樣做時,您只需要擔心在“頁面”中將一個框架居中,因為根據定義,當您將框架居中時,框架中的所有內容也將相對於整個窗口居中。

這樣做時,您無需擔心行和列的權重,因為您希望縮小內部框架以適合內容,從而不必擔心未分配的空間。 但是,我個人認為最好總是至少賦予一行和一列的權重。

這是使用內框技術的示例。 請注意,小部件是如何放置在內部框架而不是self ,並且內部框架使用pack且沒有任何選項,這導致其在其父項的頂部居中。 您還可以使用place ,如果您還希望密碼提示垂直居中,則特別方便。

def createView(self):
    inner_frame = tk.Frame(self)
    inner_frame.pack(side="top", fill="none")

    self.labelPassword = ttk.Label(inner_frame, text="Password")
    self.entryPassword = ttk.Entry(inner_frame, show = "*")
    self.buttonLogin = ttk.Button(inner_frame, text="Login", command=lambda: self.controller.show_frame(ChangePasswordPage))

    self.labelPassword.grid(row=1, column=1, sticky="e")
    self.entryPassword.grid(row=1, column=2, sticky="ew")
    self.buttonLogin.grid(row=2, column=1, columnspan=2)

摘要

布局小部件需要一種有條理的方法。 這有助於暫時為每個框架賦予不同的顏色,以便您可以查看正在增長或收縮的框架以適合其內容和/或其父級。 通常,足以查看問題出在框架,框架中的內容還是包含框架中的內容。

另外,在沒有給出明確參數的情況下,幾乎永遠不要使用packplacegrid 使用grid ,請始終至少賦予一行和一列權重。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM