python - TKinter GUI,如何使帧的大小正确?

标签 python user-interface tkinter

所以问题来了。我正在使用 Python 的 TKinter 对 GUI 进行编程,并且我需要将窗口设为特定大小。该程序的发布版本将具有 root.attributes("-fullscreen", True) 的屏幕设置所以它是全屏的,用户将无法访问任何菜单。所述屏幕将是 800x480 平板电脑屏幕。

显然我在比 800x480 大得多的屏幕上编程,所以当我创建我的 tkinter 窗口时,我正在设置 root.minsize("800x480")模拟程序所处的环境。

至于 GUI 上有什么,我会有一系列按钮和其他东西。窗口本身将被分成两个框架:按钮框架和视觉框架。按钮框架,顾名思义,将是一个完全由用于用户输入的按钮组成的框架,而视觉框架,同样显然,将只包含用户的视觉输出。

所以这是我的问题。我目前正在处理 Button Frame,但我遇到了 Frame 尺寸不正确的问题。由于我还没有完成 Visual Frame 的编程,我刚刚创建了两个 Button Frames 并将它们放置到根窗口中。两个框架都应该占据整个屏幕,但它们不是。这是我的代码:

import tkinter as tk
from tkinter import ttk

class ButtonManager(tk.Frame):

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

        self.config(background = 'green')
        self.columnconfigure(0, weight = 1)
        self.rowconfigure(0, weight = 1)

        lblFrame = LabelFrame(self, controller)
        lblFrame.grid(column = 0, row = 0, sticky = "nsew")
        lblFrame.tkraise()

        btnFrame = ButtonFrame(self, controller)
        btnFrame.grid(column = 0, row = 1, sticky = "nsew")
        btnFrame.tkraise()

        for child in self.winfo_children():
            child.grid_configure(padx = 5, pady = 5)

class LabelFrame(tk.Frame):

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

        self.config(background = 'blue')

        lblTitleBar = ttk.Label(self, text = 'TITLE BAR', background = 'grey', font = ("Arial", 20, "bold"))
        lblTitleBar.grid(column = 1, row = 1, columnspan = 4, sticky = "nsew")

        lblTextBar = ttk.Label(self, text = 'test text', background = 'grey', font = ("Arial", 16, "bold"))
        lblTextBar.grid(column = 1, row = 2, columnspan = 4, sticky = "nsew")

class ButtonFrame(tk.Frame):

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

        self.config(background = 'red')

        btn1 = ttk.Button(self, text = '1', command = lambda : print("1"))
        btn1.grid(column = 1, row = 1, columnspan = 2, rowspan = 2, sticky = "nsew")

        #Not gonna type out the code for all the buttons, but I have 2 columns, and 6 rows.  
        #The buttons on the 4th and 6th row span the columns of both rows.
        #In total there are 10 buttons

        for child in self.winfo_children():
            child.grid_configure(padx = 5, pady = 5)

class Interface(tk.Tk):

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

        container = tk.Frame(self)
        container.grid(column = 0, row = 0, sticky = "nsew")
        container.grid_rowconfigure(0, weight = 1)
        container.grid_columnconfigure(0, weight = 1)

        bMan1 = ButtonManager(container, self)
        bMan1.grid(column = 0, row = 0, sticky = "nsew")
        bMan2 = ButtonManager(container, self)
        bMan2.grid(column = 1, row = 0, sticky = "nsew")

interface = Interface()
interface.minsize(800, 480)
interface.mainloop()

正如我上面所说,我的问题是我需要每个 ButtonManager 对象在每个宽度上占据屏幕的一半。然而,我得到了 2 个小盒子和一个大的灰色区域。

随机颜色用于测试目的顺便说一句:P

编辑:我的代码中有一些复制/粘贴错误,现在它应该可以作为单个文件工作。道歉。

最佳答案

你试图一次解决太多问题。当第一次开始使用 tkinter 时,或者当第一次布局一个新的 GUI 时,有条不紊地一次只解决一个布局问题真的很有帮助。

第 1 步 - 主窗口

您已选择为 GUI 中的所有内容创建一个“容器”。因此,第一步是在尝试让其他任何事情发挥作用之前先让其发挥作用。如果它太小,那么它会导致它里面的所有东西都太小,这就是原始代码问题的一部分。

由于它是根目录中唯一的小部件,我建议使用 pack .您可以使用 grid ,但这需要三行代码而不是一行,因为使用 grid您必须记住配置至少一行和一列的权重。

从以下内容开始(并且仅以下内容):

class Interface(tk.Tk):

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

        container = tk.Frame(self, background="bisque")
        container.pack(fill="both", expand=True)

interface = Interface()
interface.minsize(800, 480)
interface.mainloop()

它看起来如何?对我来说看起来不错——蓝色完全填满了 800x480 的窗口。我们现在不再需要担心容器。

如果您想使用 grid , 删除调用 pack 的一行,并将其替换为以下三行:
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
container.grid(row=0, column=0, sticky="nsew")

第 2 步 - 容器的 child

看起来容器将包含两个 child ,对吗?左侧为按钮框,右侧为主要区域。现在让我们使用几个空框架,并在继续之前让它们工作。

您没有指定这些区域的大小,因此在此示例中,左侧的列将是屏幕大小的 1/3,右侧的列将是 2/3。如果您愿意,您可以为左侧使用固定的像素宽度,而让右侧占据其余部分。

如果你需要一个非常具体的宽度,你可以使用 place在这里,但现在我们将坚持使用 grid .

将以下内容添加到 Interface.__init__ 的底部:
    bman = ButtonManager(container, controller=self)
    main = Main(container, controller=self)

    container.grid_columnconfigure(0, weight=1)
    container.grid_columnconfigure(1, weight=2)
    container.grid_rowconfigure(0, weight=1)

    bman.grid(row=0, column=0, sticky="nsew")
    main.grid(row=0, column=1, sticky="nsew")

我们还需要为 ButtonManager 定义 stub 和 Main :
class ButtonManager(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.configure(background="green")

class Main(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.configure(background="yellow")

编码就够了。停止并运行代码,确保粉色窗口占据蓝色区域的 1/3,黄色窗口占据另外 2/3。

这可能是使用 columnconfigure 的不同值的好时机。属性(最小尺寸、重量、填充),或切换到使用 place看看它是如何工作的。

第 3 步 - 按钮管理器

我们只需要继续这个过程,再深入一层。好消息是,我们只需要关注按钮管理器内部发生的事情。除非我们添加一个太大而无法容纳的小部件,否则我们无法整体更改窗口的整体布局。

它看起来像 ButtonManager由标题和按钮区域组成。所以,让我们补充一下。由于这个框架中只有两个小部件,我们可以再次使用 pack 来节省几行代码和一些麻烦。 ,因为 pack 擅长从上到下堆叠东西。

在下面的代码中,我将标签贴在顶部,并让按钮框填充窗口的其余部分。

更改 ButtonManager看起来像这样:
class ButtonManager(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.config(background = 'green')

        lblFrame = LabelFrame(self, controller)
        btnFrame = ButtonFrame(self, controller)

        lblFrame.pack(side="top", fill="x", expand=False)
        btnFrame.pack(side="top", fill="both", expand=True)

第 4 步:标签框架

这只是一个带有几个标签的框架。同样,由于它只有几个小部件,pack将节省一点编码。您可以使用 grid如果需要,请记住您必须配置行和列的权重。
class LabelFrame(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.configure(background="blue")

        lblTitleBar = ttk.Label(self, text = 'TITLE BAR', background = 'grey', font = ("Arial", 20, "bold"))
        lblTextBar = ttk.Label(self, text = 'test text', background = 'grey', font = ("Arial", 16, "bold"))

        lblTitleBar.pack(side="top", fill="x")
        lblTextBar.pack(side="top", fill="x")

第 5 步 - ButtonFrame

最后,按钮框架。将有一个按钮网格。现在这个过程应该很熟悉了 - 创建小部件,并使用 gridpack把它们摆出来。在这种情况下 grid最有意义。
class ButtonFrame(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.configure(background="red")

        for row in range(7):
            self.grid_rowconfigure(row, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=1)

        b1 = tk.Button(self, text="Button 1")
        b2 = tk.Button(self, text="Button 2")
        b3 = tk.Button(self, text="Button 3")
        b4 = tk.Button(self, text="Button 4")
        b5 = tk.Button(self, text="Button 5")
        b6 = tk.Button(self, text="Button 6")
        b7 = tk.Button(self, text="Button 7")
        b8 = tk.Button(self, text="Button 8")
        b9 = tk.Button(self, text="Button 9")
        b10 = tk.Button(self, text="Button 10")

        b1.grid(row=0, column=0, sticky="nsew")
        b2.grid(row=0, column=1, sticky="nsew")
        b3.grid(row=1, column=0, sticky="nsew")
        b4.grid(row=1, column=1, sticky="nsew")
        b5.grid(row=2, column=0, sticky="nsew")
        b6.grid(row=2, column=1, sticky="nsew")
        b7.grid(row=3, column=0, columnspan=2, sticky="nsew")
        b8.grid(row=4, column=0, sticky="nsew")
        b9.grid(row=4, column=1, sticky="nsew")
        b10.grid(row=5, column=0, columnspan=2, sticky="nsew")

概括

如果您对 GUI 布局采用有条理的方法,那么问题将变得更容易解决,因为您一次只解决一个区域。如果您严格遵循上述所有内容,您最终会得到一个 GUI,即使您扩大或缩小窗口,它也能很好地工作。

我知道您需要一个非常具体的尺寸,但是养成编写 gui 的习惯是很好的,这些 gui 可以响应字体、分辨率和窗口尺寸的变化。

关于python - TKinter GUI,如何使帧的大小正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44830919/

相关文章:

python - 在 django 中为每种站点语言设置单独的子域

java - 基本 GUI : Computing for the area and perimeter of a rectangle, 代码有效,但 "variables are never read"

c++ - 如何在 visual studio 中创建 Windows GUI?

ios - 如何将 UILabel 与 UIViewController 的角对齐

python - 如何制作带有侧面板和内容区域的可调整大小的窗口?

Python Pyinstaller GUI Tkinter Selenium

python - 从指定列中减去 pandas 列

python - PyCharm 中的 "executable not specified"错误

python - 遍历属性列表

python - 我正在尝试使用按钮删除窗口。