Python - 使用网格布局格式化窗口
我正在自学Python,想要制作一个本地应用程序,里面有一个窗口界面。但是我在用grid()
布局屏幕时遇到了很多麻烦。我查了很多资料,试了各种代码片段,但问题还是一样,框架和小部件似乎没有正确格式化。下面的代码非常简单,但我的最终目标是掌握如何使用grid()
,这样将来我就能随心所欲地制作任何界面。
我希望能够做到以下几点:
--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 个回答
如果我理解得没错,你的问题是你无法对图形界面进行排序。其实解决方法很简单——如果你想要排序图形界面,只需要把代码按照你希望窗口显示的顺序写好就行了。比如:
--Window--
| text box |
| button |
| |
------------
-Code-
[text box code here]
[button code here]
root.mainloop()
我已经用tkinter工作很长时间了,这个方法对我有效。祝你好运,节日快乐!
LStyle
你用子框架的想法很好,但你的实现方式让问题变得比实际更复杂。一般来说,我建议你不要让不同的函数去创建小部件并把它们放到父容器里。换句话说,所有针对某个容器的 grid
或 pack
语句通常应该放在同一个函数里。
根据我的经验,完成布局的最佳方法是“分而治之”。比如,你的 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 的主要部分能够正确响应窗口的大小变化,所以我可以专注于一个部分,而不用担心它们对程序其他部分的影响。
需要注意的是,当你往某个部分添加小部件时,该部分内的行和列是独立于其他小部件的。比如,如果你在第二部分的第一列放了东西,那是指第二部分内部的第一列,而不是整个 GUI 的绝对第一列。
为了说明,假设你想把搜索标签、输入框和菜单按钮都放在第三部分(我从你的问题中无法判断你想放在哪里)。在这种情况下,标签放在第0行,占据两列,输入框和菜单按钮则放在下面,分别在不同的列。我假设你希望第一列可以随窗口大小变化。
这需要对程序进行两个修改。第一个是创建 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()