Python GUI Cookbook —— 定制 widgets
2017-12-10 19:08
1076 查看
原文链接:Python GUI Cookbook —— 定制 widgets
首先导入模块
创建消息框的回调函数,此时我们点击
将消息换成警告
显示一个错误信息
创建多选框
然后我们就可以用
来实现一些功能了
先创建一个简单的窗口看看效果:
这会产生下面这两个窗口
可以看到这并不是我们想要的
通过下面代码去掉额外的窗口
接下来对该 widget 定制一番:减小宽度,增加边框(borderwidth,bd)
给 widget 增加实际功能
还可以使用
两个 spinbox 都是浮雕(relief)风,第二个具有更大的边框
默认的 relief 属性是
relief 属性的可选值
|
首先需要添加一些面向对象(OOP)代码
给一些 widget 添加 tooltips
参考文献
Python GUI Programming Cookbook - Second Edition by Burkhard A. Meier
创建消息框——信息、警告和错误
消息框是一种用于给用户反馈的弹出式窗口,它可能是提示性的,也可能是显示潜在问题的,还有可能是指出灾难性错误的。首先导入模块
#!/usr/bin/env python3 import tkinter as tk from tkinter import ttk from tkinter import scrolledtext from tkinter import Menu from tkinter import messagebox as msg [...]
创建消息框的回调函数,此时我们点击
Help|About
[...] # Display a message box def _msgBox(): msg.showinfo('Python Message Info Box', 'A Python GUI created using tkinter:\n The year is 2017.') # Add another Menu to the Menu Bar and an item help_menu = Menu(menu_bar, tearoff=0) help_menu.add_command(label='About', command=_msgBox) menu_bar.add_cascade(label='Help', menu=help_menu) name_entered.focus() window.mainloop()
将消息换成警告
[...] # Display a message box def _msgBox(): # msg.showinfo('Python Message Info Box', # 'A Python GUI created using tkinter:\n The year is 2017.') msg.showwarning('Python Message Warning Box', 'A Python GUI Cretaed using tkinter:' '\nWarning: There might be a bug in this code.') [...]
显示一个错误信息
[...] # msg.showinfo('Python Message Info Box', # 'A Python GUI created using tkinter:\n The year is 2017.') # msg.showwarning('Python Message Warning Box', # 'A Python GUI Cretaed using tkinter:' # '\nWarning: There might be a bug in this code.') msg.showerror('Python Message Error Box', 'A Python GUI created using tkinter:' '\nError: Houston ~ We DO have a serious PROBLEM!') [...]
创建多选框
[...] # Display a message box def _msgBox(): # msg.showinfo('Python Message Info Box', # 'A Python GUI created using tkinter:\n The year is 2017.') # msg.showwarning('Python Message Warning Box', # 'A Python GUI Cretaed using tkinter:' # '\nWarning: There might be a bug in this code.') # msg.showerror('Python Message Error Box', # 'A Python GUI created using tkinter:' # '\nError: Houston ~ We DO have a serious PROBLEM!') answer = msg.askyesnocancel('Python Message Mutil Choice Box', 'Are you sure you really wish to do this?') print(answer) [...]
然后我们就可以用
If answer == True: <do something>
来实现一些功能了
创建独立的消息框
这里我们将做一个顶层窗口的消息框先创建一个简单的窗口看看效果:
from tkinter import messagebox as msg msg.showinfo('', 'Python GUI created using tkinter:\nThe year is 2017')
这会产生下面这两个窗口
可以看到这并不是我们想要的
通过下面代码去掉额外的窗口
from tkinter import messagebox as msg from tkinter import Tk root = Tk() root.withdraw() msg.showinfo('', 'Python GUI created using tkinter:\n The year is 2017')
创建 tkinter 窗体的标题
import tkinter as tk window = tk.Tk() window.title('Python GUI')
更换根窗口的图标
[...] window.iconbitmap('卷纸.ico') name_entered.focus() # Place cursor into name Entry # Start GUI window.mainloo 4000 p()
使用 spin box
[...] from tkinter import Spinbox [...] # Adding a Spinbox widget spin = Spinbox(mighty, from_=0, to=10) spin.grid(column=0, row=2) # Using a scrolled text control scrol_w = 30 scrol_h = 3 scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) scr.grid(column=0, row=3, sticky='WE', columnspan=3) [...]
接下来对该 widget 定制一番:减小宽度,增加边框(borderwidth,bd)
spin = Spinbox(mighty, from_=0, to=10, width=5, bd=8)
给 widget 增加实际功能
[...] # Spinbox callback def _spin(): value = spin.get() print(value) scr.insert(tk.INSERT, value+'\n') # Adding a Spinbox widget spin = Spinbox(mighty, from_=0, to=10, width=5, bd=8, command=_spin) [...]
还可以使用
spin = Spinbox(mighty, values=(1, 2, 4, 42, 100), width=5, bd=8, command=_spin)
widget 风格
给 spinbox 增加 bd[...] # Adding a Spinbox widget spin = Spinbox(mighty, from_=0, to=10, width=5, bd=8, command=_spin) spin.grid(column=0, row=2) Spinbox(mighty, values=(1, 2, 4, 8, 16, 32, 64), width=5, bd=20).grid(column=1, row=2) [...]
两个 spinbox 都是浮雕(relief)风,第二个具有更大的边框
默认的 relief 属性是
tk.SUNKEN
relief 属性的可选值
|
tk.SUNKEN|
tk.RAISED|
tk.FLAT|
tk.GROOVE|
tk.EIDGE|
[...] # Adding a Spinbox widget spin = Spinbox(mighty, from_=0, to=10, width=5, bd=8, command=_spin, relief=tk.GROOVE) spin.grid(column=0, row=2) Spinbox(mighty, values=(1, 2, 4, 8, 16, 32, 64), width=5, bd=8, relief='flat').grid(column=1, row=2) [...]
使用提示(tooltips)
添加一个 tooltip 应该是一件简单的事,但这里它并不像我们想象的那么简单首先需要添加一些面向对象(OOP)代码
import tkinter as tk from tkinter import ttk from tkinter import scrolledtext from tkinter import Menu from tkinter import messagebox as msg from tkinter import Spinbox class ToolTip(object): def __init__(self, widget): self.widget = widget self.tip_window = None def show_tip(self, tip_text): if self.tip_window or not tip_text: return # get size of widget x, y, _cx, cy = self.widget.bbox('insert') # calculate to display tooltip x = x + self.widget.winfo_rootx() + 25 y = y + cy + self.widget.winfo_rooty() + 25 # create new tooltip window self.tip_window = tw = tk.Toplevel(self.widget) # remove all Window Manager (wm) decorations tw.wm_overrideredirect(True) tw.wm_geometry('+%d+%d' % (x, y)) label = tk.Label(tw, text=tip_text, justify=tk.LEFT, background='#ffffe0', relief=tk.SOLID, bd=1) label.pack(ipadx=1) def hide_tip(self): tw = self.tip_window self.tip_window = None if tw: tw.destroy() def create_ToolTip(widget, text): tooltip = ToolTip(widget) def enter(event): tooltip.show_tip(text) def leave(event): tooltip.hide_tip() widget.bind('<Enter>', enter) widget.bind('<Leave>', leave) [...]
给一些 widget 添加 tooltips
[...] # Adding a Spinbox widget spin = Spinbox(mighty, from_=0, to=10, width=5, bd=8, command=_spin, relief=tk.GROOVE) spin.grid(column=0, row=2) create_ToolTip(spin, 'This is a Spinbox widget') Spinbox(mighty, values=(1, 2, 4, 8, 16, 32, 64), width=5, bd=8, relief='flat').grid(column=1, row=2) # Using a scrolled text control scrol_w = 30 scrol_h = 3 scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) scr.grid(column=0, row=3, sticky='WE', columnspan=3) # Add a Tooltip to the ScrolledText widget create_ToolTip(scr, 'This is a ScrolledText widget') [...]
添加进度条
[...] from time import sleep [...] # update progressbar in callback loop def run_progressbar(): progress_bar['maximum'] = 100 for i in range(101): sleep(0.05) # increment progressbar progress_bar['value'] = i # have to call update() in loop progress_bar.update() # reset/clear progressbar progress_bar['value'] = 0 def start_progressbar(): progress_bar.start() def stop_progressbar(): progress_bar.stop() def stop_after_second(): window.after(500, progress_bar.stop) # Create a container to hold labels buttons_frame = ttk.LabelFrame(mighty2, text=' ProgressBar ') buttons_frame.grid(column=0, row=3) # Place labels into the container element ttk.Button(buttons_frame, text=' Run Progressbar ', command=run_progressbar).grid(column=0, row=0, sticky=tk.W) ttk.Button(buttons_frame, text='Start Progressbar', command=start_progressbar).grid(column=0, row=1, sticky=tk.W) ttk.Button(buttons_frame, text='Stop immediately', command=stop_progressbar).grid(column=0, row=2, sticky=tk.W) ttk.Button(buttons_frame, text='Stop after second', command=stop_after_second).grid(column=0, row=3, sticky=tk.W) # Add a Progressbar to Tab 2 progress_bar = ttk.Progressbar(tab2, orient='horizontal', length=286, mode='determinate') progress_bar.grid(column=0, row=4, pady=2) [...]
使用 canvas widget
[...] tabControl = ttk.Notebook(window) # Create a tab tab1 = ttk.Frame(tabControl) # Add a tab tabControl.add(tab1, text='Tab 1') tab2 = ttk.Frame(tabControl) tabControl.add(tab2, text='Tab 2') tab3 = ttk.Frame(tabControl) tabControl.add(tab3, text='Tab 3') [...] # Tab 3 control tab3_frame = tk.Frame(tab3, bg='blue') tab3_frame.pack() for orange_color in range(2): canvas = tk.Canvas(tab3_frame, width=150, height=80, highlightthickness=0, bg='orange') canvas.grid(row=orange_color, column=orange_color) [...]
Full Version Code
#!/usr/bin/env python3 import tkinter as tk from tkinter import ttk from tkinter import scrolledtext from tkinter import Menu from tkinter import messagebox as msg from tkinter import Spinbox from time import sleep class ToolTip(object): def __init__(self, widget): self.widget = widget self.tip_window = None def show_tip(self, tip_text): if self.tip_window or not tip_text: return # get size of widget x, y, _cx, cy = self.widget.bbox('insert') # calculate to display tooltip x = x + self.widget.winfo_rootx() + 25 y = y + cy + self.widget.winfo_rooty() + 25 # create new tooltip window self.tip_window = tw = tk.Toplevel(self.widget) # remove all Window Manager (wm) decorations tw.wm_overrideredirect(True) tw.wm_geometry('+%d+%d' % (x, y)) label = tk.Label(tw, text=tip_text, justify=tk.LEFT, background='#ffffe0', relief=tk.SOLID, bd=1) label.pack(ipadx=1) def hide_tip(self): tw = self.tip_window self.tip_window = None if tw: tw.destroy() def create_ToolTip(widget, text): tooltip = ToolTip(widget) def enter(event): tooltip.show_tip(text) def leave(event): tooltip.hide_tip() widget.bind('<Enter>', enter) widget.bind('<Leave>', leave) # Create instance window = tk.Tk() # Add a title window.title('Python GUI') tabControl = ttk.Notebook(window) # Create a tab tab1 = ttk.Frame(tabControl) # Add a tab tabControl.add(tab1, text='Tab 1') tab2 = ttk.Frame(tabControl) tabControl.add(tab2, text='Tab 2') tab3 = ttk.Frame(tabControl) tabControl.add(tab3, text='Tab 3') # Pack to make visible tabControl.pack(expand=1, fill='both') # Tab 1 # LabelFrame using tab 1 as the parent mighty = ttk.LabelFrame(tab1, text=' Mighty Python ') mighty.grid(column=0, row=0, padx=8, pady=4) # Modify adding a Label using mighty as the parent instead of window ttk.Label(mighty, text='Enter a name:').grid(column=0, row=0, sticky='W') # Modify Button Click Function def click_me(): action.configure(text='Hello ' + name.get() + ' ' + number_chosen.get()) # Adding a Textbox Entry widget name = tk.StringVar() name_entered = ttk.Entry(mighty, width=12, textvariable=name) name_entered.grid(column=0, sticky='W') # align left/West # Adding a Button action = ttk.Button(mighty, text='Click Me!', command=click_me) action.grid(column=2, row=1) ttk.Label(mighty, text='Choose a number:').grid(column=1, row=0) number = tk.StringVar() number_chosen = ttk.Combobox(mighty, width=12, textvariable=number, state='readonly') number_chosen['values'] = (1, 2, 4, 8, 16, 32, 64, 128, 256, 562, 1024) number_chosen.grid(column=1, row=1) number_chosen.current(10) # Spinbox callback def _spin(): value = spin.get() print(value) scr.insert(tk.INSERT, value+'\n') # Adding a Spinbox widget spin = Spinbox(mighty, from_=0, to=10, width=5, bd=8, command=_spin, relief=tk.GROOVE) spin.grid(column=0, row=2) create_ToolTip(spin, 'This is a Spinbox widget') Spinbox(mighty, values=(1, 2, 4, 8, 16, 32, 64), width=5, bd=8, relief='flat').grid(column=1, row=2) # Using a scrolled text control scrol_w = 30 scrol_h = 3 scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) scr.grid(column=0, row=3, sticky='WE', columnspan=3) # Add a Tooltip to the ScrolledText widget create_ToolTip(scr, 'This is a ScrolledText widget') # Tab 2 # We are creating a container frame to hold all other widgets mighty2 = ttk.LabelFrame(tab2, text=' The Snake ') mighty2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons chVarDis = tk.IntVar() check1 = tk.Checkbutton(mighty2, text='Disabled', variable=chVarDis, state='disabled') check1.select() check1.grid(column=0, row=1, sticky=tk.W) chVarUn = tk.IntVar() check2 = tk.Checkbutton(mighty2, text='UnChecked', variable=chVarUn) check2.deselect() check2.grid(column=1, row=1, sticky=tk.W) chVarEn = tk.IntVar() check3 = tk.Checkbutton(mighty2, text='Enabled', variable=chVarEn) check3.deselect() check3.grid(column=2, row=1, sticky=tk.W) # GUI Callback function def 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 checkbutton chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) # First, we change our Radiobutton global variables into a list colors = ['Blue', 'Gold', 'Red'] # We have also changed the callback function to be zero-based, using the list # instead of module-level global variables # Radiobutton callback def radCall(): radSel = radVar.get() if radSel == 0: window.configure(background=colors[0]) elif radSel == 1: window.configure(background=colors[1]) elif radSel == 2: window.configure(background=colors[2]) # create three Radiobuttons using one variable radVar = tk.IntVar() # Now we are selecting a non-existing index value for radVar radVar.set(99) # Now we are creating all three Radiobutton widgets within one loop for col in range(3): currad = tk.Radiobutton(mighty2, text=colors[col], variable=radVar, value=col, command=radVar) currad.grid(column=col, row=2, sticky=tk.W) # update progressbar in callback loop def run_progressbar(): progress_bar['maximum'] = 100 for i in range(101): sleep(0.05) # increment progressbar progress_bar['value'] = i # have to call update() in loop progress_bar.update() # reset/clear progressbar progress_bar['value'] = 0 def start_progressbar(): progress_bar.start() def stop_progressbar(): progress_bar.stop() def stop_after_second(): window.after(500, progress_bar.stop) # Create a container to hold labels buttons_frame = ttk.LabelFrame(mighty2, text=' ProgressBar ') buttons_frame.grid(column=0, row=3) # Place labels into the container element ttk.Button(buttons_frame, text=' Run Progressbar ', command=run_progressbar).grid(column=0, row=0, sticky=tk.W) ttk.Button(buttons_frame, text='Start Progressbar', command=start_progressbar).grid(column=0, row=1, sticky=tk.W) ttk.Button(buttons_frame, text='Stop immediately', command=stop_progressbar).grid(column=0, row=2, sticky=tk.W) ttk.Button(buttons_frame, text='Stop after second', command=stop_after_second).grid(column=0, row=3, sticky=tk.W) # Add a Progressbar to Tab 2 progress_bar = ttk.Progressbar(tab2, orient='horizontal', length=286, mode='determinate') progress_bar.grid(column=0, row=4, pady=2) # Tab 3 control tab3_frame = tk.Frame(tab3, bg='blue') tab3_frame.pack() for orange_color in range(2): canvas = tk.Canvas(tab3_frame, width=150, height=80, highlightthickness=0, bg='orange') canvas.grid(row=orange_color, column=orange_color) # Exit GUI cleanly def _quit(): window.quit() window.destroy() exit() # Creating a Menu Bar menu_bar = Menu(window) window.configure(menu=menu_bar) # Add menu items file_menu = Menu(menu_bar, tearoff=0) file_menu.add_command(label='New') file_menu.add_separator() file_menu.add_command(label='Exit', command=_quit) menu_bar.add_cascade(label='File', menu=file_menu) # Display a message box def _msgBox(): # msg.showinfo('Python Message Info Box', # 'A Python GUI created using tkinter:\n The year is 2017.') # msg.showwarning('Python Message Warning Box', # 'A Python GUI Cretaed using tkinter:' # '\nWarning: There might be a bug in this code.') # msg.showerror('Python Message Error Box', # 'A Python GUI created using tkinter:' # '\nError: Houston ~ We DO have a serious PROBLEM!') answer = msg.askyesnocancel('Python Message Mutil Choice Box', 'Are you sure you really wish to do this?') print(answer) # Add another Menu to the Menu Bar and an item help_menu = Menu(menu_bar, tearoff=0) help_menu.add_command(label='About', command=_msgBox) menu_bar.add_cascade(label='Help', menu=help_menu) # Windows "ico" and Unix "xbm" # window.iconbitmap('卷纸.ico') img = tk.PhotoImage(file='卷纸.png') window.tk.call('wm', 'iconphoto', window._w, img) name_entered.focus() window.mainloop()
参考文献
Python GUI Programming Cookbook - Second Edition by Burkhard A. Meier
相关文章推荐
- Python GUI Cookbook —— 创建 GUI 窗体并添加 Widgets
- Python GUI Cookbook —— Matplotlib 图表
- Python GUI Cookbook —— 线程与网络
- Python GUI Cookbook —— 布局管理
- python cook book第三版 读书笔记2(第二章)
- 基于《PythonCookbook》的学习(4)—— 文本模式的匹配和查找
- Recipe 1.4. Aligning Strings(Python Cookbook)
- Download a web page - IronPython Cookbook
- Python Cookbook学习记录 ch2_6/7/8_2013/10/27
- python cookbook第三版学习笔记五:datetime
- Python Cookbook 第二版 汉化版 [Recipe 1.3] 测试一个对象是否为 String-like 对象
- Python Cookbook 19.18: 可前瞻的迭代器
- python字符串的操作——python cookbook
- Python cookbook(数据结构与算法)从字典中提取子集的方法示例
- python cookbook第三版学习笔记七:python解析csv,json,xml文件
- 拿到《python cookbook》
- Python cookbook(数据结构与算法)让字典保持有序的方法
- Python Cookbook 第二版 汉化版 [00-2-Preface] Part 3
- python cookbook 学习笔记 -- 1.7 将字符串逐字符或逐词反转
- 【python cookbook】python访问子字符串