8.1 系统化学习 tkinter 之布局篇
2 布局管理之 Grid如果有多个 tkinter 或者 Ttk 小部件,那么该如何布局它们?本章将利用 Grid 的方式展示 tkinter 的布局管理。2.1 在 LabelFrame 小部件中排列多个标签标签框架小部件 LabelFrame 允许我们以有组织的方式设计我们的 GUI。from tkinter import ttk, Tk# 创建一个窗口实例win = Tk()# 为窗口添加标题win.title("Python GUI")ttk.Label(text='LabelFrame').grid(column=0, row=0) # 创建一个容器(container)来保存标签。buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ')buttons_frame.grid(column=1, row=0) # 将标签放入容器元素(container element)ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky='w')ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky='w')ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky='w')# 启动 GUIwin.mainloop()
图2.1 `LabelFrame` 小部件中排列多个标签可以不填写 LabelFrame 小部件的名称,并且将 label 竖直排列:from tkinter import ttk, Tk# 创建一个窗口实例win = Tk()# 为窗口添加标题win.title("Python GUI")ttk.Label(text='LabelFrame').grid(column=0, row=0) # 创建一个容器(container)来保存标签。buttons_frame = ttk.LabelFrame(win, text='')buttons_frame.grid(column=1, row=0) # 将标签放入容器元素(container element)ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0)ttk.Label(buttons_frame, text="Label2").grid(column=0, row=1)ttk.Label(buttons_frame, text="Label3").grid(column=0, row=2)# 启动 GUIwin.mainloop()效果图:
图2.2 在 LabelFrame` 小部件中竖直排列标签2.2 使用填充添加小部件周围的空间上面的 LabelFrame 看起来有点拥挤,因为它与主窗口混合到底部。现在让我们来解决这个问题:在 buttons_frame 内部添加空白:for child in buttons_frame.winfo_children(): child.grid_configure(padx=8, pady=4)效果图:
图2.3 使用填充在 `buttons_frame` 内部添加空白也可以直接在 buttons_frame 上添加空白:buttons_frame.grid(column=0, row=1, padx=20, pady=40)
图2.4 使用填充在 `buttons_frame` 周围添加空白综合上述两种添加空白的方法得到:
图2.5 使用填充添加小部件周围的空间2.3 创建菜单栏创建菜单栏是 GUI 的“主菜”:from tkinter import Tk, Menu, ttk# 创建一个窗口实例win = Tk()# 为窗口添加标题win.title("Python GUI")# 创建 Menu Barmenu_bar = Menu(win)win.config(menu=menu_bar)# 创建 menu 并添加 menu itemsfile_menu = Menu(menu_bar) # 创建File menufile_menu.add_command(label="新建") # 添加 File menu item# 添加分隔线file_menu.add_separator()file_menu.add_command(label="退出")# 添加File menu 到 menu bar 并给予一个标签menu_bar.add_cascade(label="文件", menu=file_menu)# 启动 GUIwin.mainloop()效果图:
图2.6 可分离的创建菜单栏通过将 tearoff 属性传递给菜单的构造函数,我们可以删除默认情况下出现在菜单中第一个菜单项上方的第一个虚线来禁用菜单栏的分离:file_menu = Menu(menu_bar, tearoff=0)效果图:
图2.7 不可分离的创建菜单栏在菜单栏添加新的菜单:# 将另一个菜单添加到菜单栏和项目help_menu = Menu(menu_bar, tearoff=0)menu_bar.add_cascade(label="帮助", menu=help_menu)help_menu.add_command(label="关于")效果图:
图2.8 添加“帮助”菜单此时,我们的 GUI 具有菜单栏和两个包含一些菜单项的菜单。在我们添加一些命令之前,单击它们不会执行任何操作。这就是我们接下来要做的。在创建菜单栏时添加以下代码:# 退出 GUIdef _quit(): win.quit() win.destroy()接着,在“退出”菜单选项中添加 command 配置选项:file_menu.add_command(label="退出", command=_quit)现在,当我们单击 "退出" 菜单项时,我们的应用程序确实会退出。我们也需要为“关于”菜单创建命令弹出消息盒子:from tkinter import messagebox as msgdef _msgBox(): msg.showinfo(title="Python 消息信息框", message='使用 tkinter:\n 年份是 2020 年创建的 Python GUI。') ...help_menu.add_command(label="关于", command=_msgBox) # 单击时显示消息框# 启动 GUIwin.mainloop()效果图:
图2.9 消息盒子 Info也可以设定为警告:def _msgBox(): msg.showwarning('Python 消息警告框', '使用 tkinter 创建的 Python GUI: \n警告:此代码中可能存在 bug。')显示:
图2.10 消息警告框弹出错误框:def _msgBox(): msg.showerror('Python 消息错误框', '使用 tkinter 创建的 Python GUI: \n错误:我们确实有一个严重的问题!')显示:
图2.11 错误框弹出多选框:def _msgBox(): answer = msg.askyesnocancel("Python 消息多选择框", "你确定你真的想这么做吗?") print(answer)显示:
图2.12 多选框此框是有返回值的,选择"是","否","取消" 分别返回:True、False、None。2.4 创建选项卡式小部件:ttk.Notebook为了充分地利用窗口的空间,创建选项卡式小部件(tabbed widgets )是十分有必要的:from tkinter import Tk, Menu, ttk# 创建一个窗口实例win = Tk()# 为窗口添加标题win.title("Python GUI")# 创建 Tab Control(选项卡控件)tabControl = ttk.Notebook(win)tab1 = ttk.Frame(tabControl) # 创建选项卡(tab)tabControl.add(tab1, text='Tab 1') # 添加tabtab2 = ttk.Frame(tabControl) # 再添加一个 tabtabControl.add(tab2, text='Tab 2')tabControl.pack(expand=1, fill="both") # pack 以使其可见# 启动 GUIwin.mainloop()效果图:
图2.13 创建带有选项卡的 Notebook为其中一个选项卡添加 LabelFrame:from tkinter import Tk, Menu, ttk...# 使用 tab1 作为父级的标签框架mighty = ttk.LabelFrame(tab1, text=' Mighty Python ')mighty.grid(column=0, row=0, padx=8, pady=4)# 使用mighty作为父级的标签a_label = ttk.Label(mighty, text="键入名称:")a_label.grid(column=0, row=0, sticky='W')# 启动 GUIwin.mainloop()
图2.14 为其中一个选项卡添加 LabelFrame