首页 文章

tkinter grid:在帧高和宽度上分配行和列

提问于
浏览
0

在Mac OS上使用python 3.4.1我试图在名为“lowerframe”的子帧中使用网格几何管理器同等地分发标签和条目小部件 .

我目前的MWE如下所示:

#!/usr/bin/env python3

from tkinter import *
from tkinter import ttk

class Window(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        # create master window
        self.master = master

        # create root window on initialization
        self.create_rootwindow()

    def create_rootwindow(self):
        self.master.title("GUI")
        self.master.geometry("1024x748")
        self.master.resizable(width=FALSE, height=FALSE)

        self.create_upperframe()
        self.create_lowerframe()
        self.create_inputentries()
        self.create_btnframe()
        self.create_inputbtn()

    def create_upperframe(self):
        self.upperframe = Frame(self.master, width=980, height=490)
        self.upperframe.config(background="#339900")
        self.upperframe.place(x=20, y=10)

    def create_lowerframe(self):
        self.lowerframe = Frame(self.master, width=830, height=200)
        self.lowerframe.config(background="#336699")
        self.lowerframe.place(x=20, y=530)

    def create_inputentries(self):
        self.create_lowerframe()

        parameternames = [
            ('a', 'U'), ('b', 'U'), ('c', 'U'), ('d', 'U'), ('e', 'U'),
            ('f', 'U'), ('g', 'U'), ('h', 'U'), ('i', 'U'), ('j', 'U'),
            ('k', 'U'), ('l', 'U'), ('m', 'U'), ('n', 'U'), ('o', 'U'),
            ('p', 'U'), ('q', 'U'), ('r', 'U'), ('s', 'U'), ('t', 'U')]

        for i, data in enumerate(parameternames):
            r = i % 5
            c = (i // 5) * 3
            Label(self.lowerframe, text=data[0]).grid(row=r, column=c, pady=4, padx=0)
            Entry(self.lowerframe, width=10).grid(row=r, column=c+1, pady=4, padx=0)
            Label(self.lowerframe, text=data[1]).grid(row=r, column=c+2, pady=4, padx=0)

    def create_btnframe(self):
        self.btnframe = Frame(self.master, width=130, height=200)
        self.btnframe.place(x=870, y=530)

    def create_inputbtn(self):
        self.create_btnframe()

        startanalysis_btn = Button(self.btnframe, text="Start Analysis", width=12, command=self.do_nothing)
        startanalysis_btn.place(x=0, y=0)

        abortanalysis_btn = Button(self.btnframe, text="Abort Analysis", width=12, command=self.do_nothing)
        abortanalysis_btn.place(x=0, y=50)

        resetanalysis_btn = Button(self.btnframe, text="Reset Analysis", width=12, command=self.do_nothing)
        resetanalysis_btn.place(x=0, y=100)

        showresults_btn = Button(self.btnframe, text="Show Results", width=12, command=self.do_nothing)
        showresults_btn.place(x=0, y=200, anchor=SW)

    def do_nothing(self):
        pass

root = Tk()

app = Window(root)

root.mainloop()

如您所见,较低的蓝色框架(称为“下框架”)中的每个“小组”小部件由带有描述的标签(此处为“a”到“t”),条目小部件和另一个标签小部件组成 . 以输入值为单位(对于所有标签,此处为“U”) .

使用这些“集合”我需要创建五行和四个“设置列”(当前使用网格几何管理器的12列) . 我的目标是将这些行和“设置列”分配到指定的下层高度和宽度 .

  • 编辑:我上传了一个sketch到我的Dropbox文件夹,显示结果应该是什么样子 .

1 回答

  • 2

    编写代码的方式使得修改非常困难 . 首先,作为一个经验法则,你永远不应该使用 place . 根本没有必要,因为 packgrid 提供了更多功能 .

    其次,作为另一个经验法则,父母应负责布置其子项 - 没有创建框架的函数也调用 gridpackplace 将其自身置于其父级中 . 如果您决定更改布局,则最终必须更改一堆函数而不是一个 .

    最后,当使用网格时,如果希望它们增长以填充其包含的窗口,则需要为行和列提供“权重” .

    以下是我将如何重写代码:

    from tkinter import *
    
    class Window(Frame):
        def __init__(self, master=None):
            Frame.__init__(self, master)
            # create master window
            self.master = master
    
            # create root window on initialization
            self.create_rootwindow()
    
        def create_rootwindow(self):
            self.master.title("GUI")
            self.master.geometry("1024x748")
    
            self.create_upperframe()
            self.create_lowerframe()
            self.create_inputentries()
            self.create_btnframe()
            self.create_inputbtn()
    
            self.upperframe.pack(side="top", fill="both", expand=True, padx=4)
            self.lowerframe.pack(side="left", fill="both", expand=True, padx=4, pady=4)
            self.btnframe.pack(side="right", fill="both", padx=4, pady=4)
    
        def create_upperframe(self):
            self.upperframe = Frame(self.master, width=980, height=490)
            self.upperframe.config(background="#339900")
    
        def create_lowerframe(self):
            self.lowerframe = Frame(self.master, width=830, height=200)
            self.lowerframe.config(background="#336699")
    
        def create_inputentries(self):
            self.create_lowerframe()
    
            parameternames = [
                ('a', 'U'), ('b', 'U'), ('c', 'U'), ('d', 'U'), ('e', 'U'),
                ('f', 'U'), ('g', 'U'), ('h', 'U'), ('i', 'U'), ('j', 'U'),
                ('k', 'U'), ('l', 'U'), ('m', 'U'), ('n', 'U'), ('o', 'U'),
                ('p', 'U'), ('q', 'U'), ('r', 'U'), ('s', 'U'), ('t', 'U')]
    
            for i, data in enumerate(parameternames):
                r = i % 5
                c = (i // 5) * 3
                Label(self.lowerframe, text=data[0]).grid(row=r, column=c, pady=4, padx=0, sticky="nsew")
                Entry(self.lowerframe, width=10).grid(row=r, column=c+1, pady=4, padx=0, sticky="ew")
                Label(self.lowerframe, text=data[1]).grid(row=r, column=c+2, pady=4, padx=0, sticky="nswe")
    
                self.lowerframe.grid_columnconfigure(c+1, weight=1)
    
    
        def create_btnframe(self):
            self.btnframe = Frame(self.master, width=130, height=200)
    
        def create_inputbtn(self):
            self.create_btnframe()
    
            startanalysis_btn = Button(self.btnframe, text="Start Analysis", width=12, command=self.do_nothing)
            abortanalysis_btn = Button(self.btnframe, text="Abort Analysis", width=12, command=self.do_nothing)
            resetanalysis_btn = Button(self.btnframe, text="Reset Analysis", width=12, command=self.do_nothing)
            showresults_btn = Button(self.btnframe, text="Show Results", width=12, command=self.do_nothing)
    
            startanalysis_btn.pack(side="top", fill="x")
            abortanalysis_btn.pack(side="top", fill="x")
            resetanalysis_btn.pack(side="top", fill="x")
            showresults_btn.pack(side="top", fill="x")
    
        def do_nothing(self):
            pass
    
    root = Tk()
    app = Window(root)
    root.mainloop()
    

    Things to notice:

    • 我用 pack 替换了 place 的所有用法(尽管 grid 也能正常工作)

    • 我在创建主要区域之后将它们分组在一起

    • 我将按钮的 pack 组合在一起,使其可视化和修改变得更加容易

    • 我在底部框架中为具有输入小部件的列添加了权重 . 这会导致这些列增大或缩小以填充任何额外空间

    • 我删除了可调整大小为false的设置 . 一般来说,我认为应该允许用户选择GUI的大小 . 此外,它说明通过使用 pack 和/或 grid 而不是 place ,您可以获得适当的调整大小行为而无需任何额外的努力 . 如果你真的认为自己比用户更了解,那么你可以把它放回去 .

    代码现在具有良好的调整大小行为,条目小部件的网格扩展以填充其容器,并且函数紧密耦合较少,因为创建框架的函数不必知道该框架将如何显示 .

相关问题