Python GUI Cookbook —— 布局管理
来源:互联网 发布:软件著作权申请网址 编辑:程序博客网 时间:2024/06/07 16:47
原文链接:Python GUI Cookbook —— 布局管理
在标签框架中排列多个标签
LabelFrame
可以让我们有组织的的设计 GUI。
[...]# Create a container to hold labelsbuttons_frame = ttk.LabelFrame(window, text=' Label in a Frame')buttons_frame.grid(column=0, row=7)# buttons_frame.grid(column=1, row=6)# Place labels into the container elementttk.Label(buttons_frame, text='Label1').grid(column=0, row=0, sticky=tk.W)ttk.Label(buttons_frame, text='Lable2').grid(column=1, row=0, sticky=tk.W)ttk.Label(buttons_frame, text='Label3').grid(column=2, row=0, sticky=tk.W)name_entered.focus() # Place cursor into name Entry# Start GUIwindow.mainloop()
也可以垂直摆放
# Create a container to hold labelsbuttons_frame = ttk.LabelFrame(window, text=' Label in a Frame')buttons_frame.grid(column=0, row=7)# buttons_frame.grid(column=1, row=6)# Place labels into the container elementttk.Label(buttons_frame, text='Label1').grid(column=0, row=0, sticky=tk.W)ttk.Label(buttons_frame, text='Lable2').grid(column=0, row=1, sticky=tk.W)ttk.Label(buttons_frame, text='Label3').grid(column=0, row=2, sticky=tk.W)name_entered.focus() # Place cursor into name Entry# Start GUIwindow.mainloop()
使用填充增加 widget 周围的空间
tkinter 因 GUI 丑陋而闻名,然而这种情况在版本号 8.5 后发生了巨大的变化。Python 3.6 带有 tkinter 8.6。
给之前的代码添加 padx
和 pady
。
[...]buttons_frame.grid(column=0, row=7, padx=20, pady=40)[...]
给 LabelFrame
包含的标签添加一些空间
[...]ttk.Label(buttons_frame, text='Lable2').grid(column=0, row=1)ttk.Label(buttons_frame, text='Label3').grid(column=0, row=2)for child in buttons_frame.winfo_children(): child.grid_configure(padx=8, pady=4)name_entered.focus() # Place cursor into name Entry# Start GUIwindow.mainloop()
grid_configure()
可以让我们能够在主循环显示 UI 之前修改它们。所以不必在首次创建 widget 时硬编码这些值。winfo_children()
返回 buttons_frame 的子 widgets。
还不知道 labels 右边的空间的大小
[...]# Place labels into the container elementttk.Label(buttons_frame, text='Label1 -- sooooooo much looooooooonger...').grid(column=0, row=0)ttk.Label(buttons_frame, text='Lable2').grid(column=0, row=1)ttk.Label(buttons_frame, text='Label3').grid(column=0, row=2)[...]
可以移除 LabelFrme
的名字。看看 padx 的效果
[...]buttons_frame = ttk.LabelFrame(window, text='')[...]
widgets 动态扩展 GUI
你可能已经看到了 widget 能够自动扩展所需空间以便直观地显示文本。
对于网格管理器,其列的宽度取决于该列中最长的名字或 widget。
由于显示
LaqbelFrame
标题的文本属性比上面的Enter a name:
label 和 textbox entry 都长,所以这两个 widget 都依据新宽度,动态地中心对齐到 column 0。column 0 的
Checkbutton
和Radiobutton
没有中心对齐,因为使用了sticky=tk.W
属性。
通过在框架中放入框架来组织 GUI widgets
这里我们将创建一个顶层框架来包含其他 widget
添加下面的代码到我们的 Python 模块
#!/usr/bin/env python3import tkinter as tkfrom tkinter import ttkfrom tkinter import scrolledtext# Create instancewindow = tk.Tk()# Add a titlewindow.title("My First Python GUI")# We are creating a container frame to hold all other widgetsmighty = ttk.LabelFrame(window, text=' Mighty Python ')mighty.grid(column=0, row=0, padx=8, pady=4)[...]
接下来将 mighty
作为父 widget
,替换 window
。如下所示:
[...]# Modify adding a Label using mighty as the parent instead of windowa_label = ttk.Label(mighty, text = 'Enter a number:')a_label.grid(column=0, row=0)[...]
创建菜单栏
首先需要从 tkinter 中导入 Menu 类
#!/usr/bin/env python3import tkinter as tkfrom tkinter import ttkfrom tkinter import scrolledtextfrom tkinter import Menu# Create instancewindow = tk.Tk()[...]
添加菜单项
[...]# Creating a Menu Barmenu_bar = Menu(window)window.config(menu=menu_bar)# Creating menu and add menu itemsfile_menu = Menu(menu_bar) # create File menufile_menu.add_command(label='New') # add file menu itemmenu_bar.add_cascade(label='File', menu=file_menu) # add File menu to menu barname_entered.focus() # Place cursor into name Entry# Start GUIwindow.mainloop()
如果你对这段代码有一点困惑的话,请不要担心,这仅仅是 tkinter 创建 menubar 的语法,并不很 Pythonic。
添加第二个菜单项
[...]# Creating a Menu Barmenu_bar = Menu(window)window.config(menu=menu_bar)# Creating menu and add menu itemsfile_menu = Menu(menu_bar) # create File menufile_menu.add_command(label='New') # add file menu itemfile_menu.add_command(label='Exit')menu_bar.add_cascade(label='File', menu=file_menu) # add File menu to menu barname_entered.focus() # Place cursor into name Entry# Start GUIwindow.mainloop()
在两个菜单项中间添加分隔线
- 通过传
tearoff
属性到菜单的构造器,移除第一个 dashed line - 通过下面代码添加分隔线
[...]# Creating menu and add menu itemsfile_menu = Menu(menu_bar, tearoff=0) # create File menufile_menu.add_command(label='New') # add file menu itemfile_menu.add_separator()file_menu.add_command(label='Exit')menu_bar.add_cascade(label='File', menu=file_menu) # add File menu to menu barname_entered.focus() # Place cursor into name Entry# Start GUIwindow.mainloop()
接下来添加水平的第二个菜单
[...]# Adding another Menu to the Menu Bar and an itemhelp_menu = Menu(menu_bar, tearoff=0)help_menu.add_command(label='About')menu_bar.add_cascade(label='Help', menu=help_menu)[...]
现在,我们的菜单项点击过后还没有反应,因此我们需要添加一些 commands 到菜单项
[...]# Exit GUI cleanlydef _quit(): window.quit() window.destroy() exit()# Creating a Menu Barmenu_bar = Menu(window)window.config(menu=menu_bar)# Creating menu and add menu itemsfile_menu = Menu(menu_bar, tearoff=0) # create File menufile_menu.add_command(label='New') # add file menu itemfile_menu.add_separator()file_menu.add_command(label='Exit', command=_quit)menu_bar.add_cascade(label='File', menu=file_menu) # add File menu to menu bar[...]
现在当我们点击 Exit,程序就会立刻退出。
创建选项卡式 widgets
创建一个新的 Python 模块
#!/usr/bin/env python3import tkinter as tkfrom tkinter import ttkwindow = tk.Tk() # Create instancewindow.title('Python GUI') # Add a titletabControl = ttk.Notebook(window) # Create Tab Controltab1 = ttk.Frame(tabControl) # Create a TabtabControl.add(tab1, text='Tab 1') # Add the TabtabControl.pack(expand=1, fill='both') # Pack to make visiblewindow.mainloop()
添加第二个 Tab
#!/usr/bin/env python3import tkinter as tkfrom tkinter import ttkwindow = tk.Tk() # Create instancewindow.title('Python GUI') # Add a titletabControl = ttk.Notebook(window) # Create Tab Controltab1 = ttk.Frame(tabControl) # Create a TabtabControl.add(tab1, text='Tab 1') # Add the Tabtab2 = ttk.Frame(tabControl) # Create second TabtabControl.add(tab2, text='Tab 2') # Add second TabtabControl.pack(expand=1, fill='both') # Pack to make visiblewindow.mainloop()
在 Tab 1 中写一些内容
#!/usr/bin/env python3import tkinter as tkfrom tkinter import ttkwindow = tk.Tk() # Create instancewindow.title('Python GUI') # Add a titletabControl = ttk.Notebook(window) # Create Tab Controltab1 = ttk.Frame(tabControl) # Create a TabtabControl.add(tab1, text='Tab 1') # Add the Tabtab2 = ttk.Frame(tabControl) # Create second TabtabControl.add(tab2, text='Tab 2') # Add second TabtabControl.pack(expand=1, fill='both') # Pack to make visible# LabelFrame using tab1 as the parentmighty = ttk.LabelFrame(tab1, text=' Mighty Python ')mighty.grid(column=0, row=0, padx=8, pady=4)# Label using mighty as the parenta_label = ttk.Label(mighty, text=' Enter a number: ')a_label.grid(column=0, row=0, sticky='W')window.mainloop()
再加一些内容,好看清标题
#!/usr/bin/env python3import tkinter as tkfrom tkinter import ttkfrom tkinter import scrolledtextwindow = tk.Tk() # Create instancewindow.title('Python GUI') # Add a titletabControl = ttk.Notebook(window) # Create Tab Controltab1 = ttk.Frame(tabControl) # Create a TabtabControl.add(tab1, text='Tab 1') # Add the Tabtab2 = ttk.Frame(tabControl) # Create second TabtabControl.add(tab2, text='Tab 2') # Add second TabtabControl.pack(expand=1, fill='both') # Pack to make visible# LabelFrame using tab1 as the parentmighty = ttk.LabelFrame(tab1, text=' Mighty Python ')mighty.grid(column=0, row=0, padx=8, pady=4)# Label using mighty as the parenta_label = ttk.Label(mighty, text=' Enter a number: ')a_label.grid(column=0, row=0, sticky='W')# Modified Button click Event Functiondef click_me(): action.configure(text='Hello ' + name.get() + ' ' + number_chosen.get())# Adding a Textbox Entry widgetname = tk.StringVar()name_entered = ttk.Entry(mighty, width=12, textvariable=name)name_entered.grid(column=0, row=1, sticky='W') # column 0# Adding a Buttonaction = ttk.Button(mighty, text="Click Me!", command=click_me) action.grid(column=2, row=1, sticky='W') # change column to 2ttk.Label(mighty, text='Choose a number:').grid(column=1, row=0, sticky='W')number = tk.StringVar()number_chosen = ttk.Combobox(mighty, width=12, textvariable=number, state='readonly')number_chosen['values'] = (1, 2, 4, 42, 100)number_chosen.grid(column=1, row=1, sticky='W') # Combobox in column 1number_chosen.current(4)# Using a scrlled text controlscrol_w = 30scrol_h = 3scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD)scr.grid(column=0, sticky='WE', columnspan=3)window.mainloop()
给 Tab 2 也加上内容
[...]# Creating three checkbuttonschVarDis = tk.IntVar()check1 = tk.Checkbutton(snake, text='Disabled', variable=chVarDis, state='disabled')check1.select()check1.grid(column=0, row=0, sticky='W')chVarUn = tk.IntVar()check2 = tk.Checkbutton(snake, text='UnChecked', variable=chVarUn)check2.deselect()check2.grid(column=1, row=0, sticky='W')chVarEn = tk.IntVar()check3 = tk.Checkbutton(snake, text='Enabled', variable=chVarEn)check3.deselect()check3.grid(column=2, row=0, sticky='W')# GUI callback functiondef checkCallback(*ignoredArgs): if chVarUn.get(): check3.configure(state='disabled') else: check3.configure(state='normal') if chVarEn.get(): check2.configure(state='disabled') else: check2.configure(state='normal')# trace the state of the two checkbuttonchVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback())chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback())# First, we change our Radiobutton globals variables into a listcolors = ['Blue', 'Gold', 'Red']# We have also changed the callback function to be zero-based, using list# instead of module-level global variables# Radiobutton Callbackdef radCall(): radSel = radVar.get() if radSel == 0: snake.configure(background=colors[0]) # now zero-based and using list elif radSel == 1: snake.configure(background=colors[1]) elif radSel == 2: snake.configure(background=colors[2])# Create three Radiobuttons using one variableradVar = tk.IntVar()# Next we are selecting a non-existing index value for radVarradVar.set(99)# Now we are creating all three Radiobutton widgets within one loopfor col in range(3): curRad = tk.Radiobutton(snake, text=colors[col], variable=radVar, value=col, command=radCall) curRad.grid(column=col, row=1, sticky=tk.W)# Create a container to hold labelsbuttons_frame = ttk.LabelFrame(snake, text=' Labels in a Frame ')buttons_frame.grid(column=0, row=2)# buttons_frame.grid(column=1, row=6)# Place labels into the container elementttk.Label(buttons_frame, text='Label1').grid(column=0, row=0)ttk.Label(buttons_frame, text='Lable2').grid(column=0, row=1)ttk.Label(buttons_frame, text='Label3').grid(column=0, row=2)for child in buttons_frame.winfo_children(): child.grid_configure(padx=8, pady=4)window.mainloop()
点击 Radiobutton
发现不起作用了,那么我们改变它们的功能
[...]# Radiobutton Callbackdef radCall(): radSel = radVar.get() if radSel == 0: snake.configure(text='Blue') # now zero-based and using list elif radSel == 1: snake.configure(text='Gold') elif radSel == 2: snake.configure(text='Red')[...]
使用网格布局管理器
- 如果我们不指明 row 的值,tkinter 会自动完成加 1 操作。
参考文献
- Python GUI Programming Cookbook - Second Edition by Burkhard A. Meier
- Python GUI Cookbook —— 布局管理
- Python GUI Cookbook —— 定制 widgets
- Python GUI Cookbook —— 创建 GUI 窗体并添加 Widgets
- Python GUI之tkinter布局管理
- GUI—布局、监听器
- Python Cookbook 2——Python技巧
- 黑马程序员----GUI布局管理
- python字符串的操作——python cookbook
- Python图形GUI工具包tkinter如何调整元件在窗口中的位置几何布局管理
- Python图形GUI工具包tkinter如何调整元件在窗口中的位置几何布局管理
- python—Tkinter GUI编程
- Python Cookbook 2 ——搜索和排序
- data imputation —— Python Data Science Cookbook
- sampling brief —— python data science cookbook
- Removing stop words —— Python Data Science CookBook
- Python CookBook笔记——数据结构与算法
- C++ GUI Qt4编程-布局管理
- Python Cookbook
- 敌兵布阵
- java 8中foreach的理解
- Windows下配置 Cmder 设置环境
- 17.12.04,web学习第十八天,还有一年,努力吧青年EL和JSTL
- kail linux 几种代理方式
- Python GUI Cookbook —— 布局管理
- CentOS配置virtualenv
- 上传plupload的使用
- openvr显示相关接口
- 机器学习的算法——用最通俗的例子去理解
- 通过函数名的字符串来调用这个函数
- javascript之异常捕获
- 多线程之并发与并行概念总结
- 读