Python - 使用网格布局格式化窗口

时间:2013-03-22 15:20:34

标签: python user-interface grid tkinter

我正在教自己Python并尝试构建一个使用窗口GUI的本地应用程序。我在尝试使用grid()布局屏幕时遇到了很多麻烦。我搜索并尝试了许多不同的代码片段,但我有同样的问题,框架和小部件似乎不是格式化。下面的代码非常简单,但我的最终目标是掌握如何使用grid(),以便我可以构建我喜欢的任何GUI。

我希望能够做到以下几点:

--Window-----------------
| Section 1 | Section 2 |
|           |           |
-------------------------
| Section 3             |
|                       |
|                       |
-------------------------

from Tkinter import Button, Frame, Entry, Tk, Label, Menubutton, Menu, IntVar

class MainScreen(Frame):
def __init__(self, master):
    Frame.__init__(self, master)
    self.grid()
    self.searchSection()
    self.quitButton()


def searchSection(self):
    # Create Search Section
    self.searchFrame = Frame(self.master, bg='grey', relief='sunken', width=200, height=200)
    self.searchFrame.grid(row=0, column=0, rowspan=5, columnspan=30, sticky="wens")
    Label(self.searchFrame, text="Search :", bg='grey').grid(row=1, column=1, columnspan=20, sticky='w')
    self.searchField = Entry(self.searchFrame)
    self.searchField.grid(row=2, column=1, columnspan=7, sticky='w')
    #Create Menu Options
    self.search = Menubutton(self.searchFrame, text = "Search", bg='grey')
    self.search.grid(row=2, column=8, columnspan=3, sticky='w')
    self.search.menu = Menu(self.search, tearoff = 0)
    self.search['menu'] = self.search.menu       
    self.SearchType1Var = IntVar()
    self.search.menu.add_checkbutton(label="SearchType1", variable = self.SearchType1Var)


def quitButton(self):
    ## Provide a quit button to exit the rogram
    self.quitFrame = Frame(self.master, bg='grey', width=50, height=50)
    self.quitFrame.grid(row=0, column=20, rowspan=5, columnspan=5, sticky='ewns')
    self.quitButton = Button(self.quitFrame, text="Quit", command=exit)
    self.quitButton.grid()


if __name__ == '__main__':

root = Tk()
root.title("Learn Grid GUI")
root.geometry("800x600+200+150")
main = MainScreen(root)
root.mainloop()

2 个答案:

答案 0 :(得分:2)

您使用子帧的直觉很好,但是您的实施会使问题变得更加困难。根据一般的经验法则,我建议反对使用不同的函数创建小部件并将它们放在父级中。换句话说,给定容器的所有gridpack语句通常都应该在同一个函数中。

根据我的经验,完成布局的最佳方法是“分而治之”。例如,您的ascii绘图显示了三个部分。从那开始,只有那个。创建三个框架,每个部分一个。在尝试向其添加任何内容之前,将它们正确放置在容器中。

当我这样做时,我首先为每个框架提供一个独特的颜色和一个明确的大小,仅用于可视化目的。例如:

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, master, *args, **kwargs):
        tk.Frame.__init__(self, master, *args, **kwargs)
        self.master = master
        self.s1 = tk.Frame(self, background="pink", width=200, height=200)
        self.s2 = tk.Frame(self, background="blue", width=200, height=200)
        self.s3 = tk.Frame(self, background="bisque", width=200, height=200)

        self.s1.grid(row=0, column=0, sticky="nsew")
        self.s2.grid(row=0, column=1, sticky="nsew")
        self.s3.grid(row=1, column=0, columnspan=2, sticky="nsew")

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

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

一旦我正常工作并正确调整大小,我就可以继续添加小部件,一次一个部分。由于我已经让GUI的主要部分适当地响应窗口调整大小,我可以将所有精力集中在一个部分,而不用担心它们如何影响程序的其余部分。

重要的是要知道,当您向其中一个部分添加窗口小部件时,该部分中的行和列独立于任何其他窗口小部件。例如,如果您在第2部分的第1列中添加了某些内容,那么第1部分中的第1列 第2部分,而不是整个GUI的绝对列。

为了便于说明,我们假设您希望搜索标签,条目小部件和菜单按钮全部放在第3部分(我无法从您的问题中找出您希望它们去的地方)。在这种情况下,标签位于第0行并跨越两列,条目小部件和menubutton位于不同的列中。我假设您希望第一列增长和缩小。

这需要对程序进行两次修改。第一个是创建searchSection函数,它在搜索部分创建小部件。第二个修改是在GUI的构造函数中调用此函数。

这是一个完全正常的最终版本:

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, master, *args, **kwargs):
        tk.Frame.__init__(self, master, *args, **kwargs)

        self.s1 = tk.Frame(self, background="pink", width=200, height=200)
        self.s2 = tk.Frame(self, background="blue", width=200, height=200)
        self.s3 = tk.Frame(self, background="bisque", width=200, height=200)

        self.s1.grid(row=0, column=0, sticky="nsew")
        self.s2.grid(row=0, column=1, sticky="nsew")
        self.s3.grid(row=1, column=0, columnspan=2, sticky="nsew")

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

        # now create the search section
        self.searchSection(self.s1)

    def searchSection(self, parent):
        l = tk.Label(parent, text="Search :", bg='grey')
        self.searchField = tk.Entry(parent)
        self.search = tk.Menubutton(parent, text="Search", bg="grey")
        self.search.menu = tk.Menu(self.search, tearoff = 0)
        self.search['menu'] = self.search.menu
        self.SearchType1Var = tk.IntVar()
        self.search.menu.add_checkbutton(label="SearchType1", 
                                         variable = self.SearchType1Var)

        l.grid(row=0, column=0, columnspan=2, sticky='w')
        self.searchField.grid(row=1, column=0, sticky="ew")
        self.search.grid(row=1, column=1, sticky="ew")

        parent.grid_columnconfigure(0, weight=1)

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

答案 1 :(得分:0)

如果我理解正确,您的问题是您无法对GUI进行排序。 答案非常简单 - 如果您想对GUI进行排序,只需将代码放在您希望窗口显示的顺序中。例如:

 --Window--
| text box |
|  button  |
|          |
------------

-Code-
[text box code here]
[button code here]
root.mainloop()

我已经和tkinter合作了很长时间,它对我有用。 祝你好运,庆祝圣日快乐!

LStyle