-
1、圖形化界面設計的基本理解
當前流行的計算機桌面應用程序大多數(shù)為圖形化用戶界面(Graphic User Interface,GUI),即通過鼠標對菜單嵌灰、按鈕等圖形化元素觸發(fā)指令,并從標簽票顾、對話框等圖型化顯示容器中獲取人機對話信息础浮。
Python自帶了tkinter 模塊,實質(zhì)上是一種流行的面向?qū)ο蟮腉UI工具包 TK 的Python編程接口奠骄,提供了快速便利地創(chuàng)建GUI應用程序的方法豆同。其圖像化編程的基本步驟通常包括:- 導入 tkinter 模塊
- 創(chuàng)建 GUI 根窗體
- 添加人機交互控件并編寫相應的函數(shù)。
- 在主事件循環(huán)中等待用戶觸發(fā)事件響應含鳞。
-
2影锈、窗體控件布局
-
2.1、根窗體是圖像化應用程序的根控制器蝉绷,是tkinter的底層控件的實例鸭廷。當導入tkinter模塊后,調(diào)用 Tk()方法可初始化一個根窗體實例 root ,用 title() 方法可設置其標題文字熔吗,用geometry()方法可以設置窗體的大辛敬病(以像素為單位)。將其置于主循環(huán)中桅狠,除非用戶關閉讼载,否則程序始終處于運行狀態(tài)轿秧。執(zhí)行該程序,一個窗體就呈現(xiàn)出來了咨堤。在這個主循環(huán)的根窗體中菇篡,可持續(xù)呈現(xiàn)中的其他可視化控件實例,監(jiān)測事件的發(fā)生并執(zhí)行相應的處理程序一喘。下面是根窗體呈現(xiàn)示例:
from tkinter import * root= Tk() root.title('我的第一個Python窗體') root.geometry('240x240') # 這里的乘號不是 * 驱还,而是小寫英文字母 x root.mainloop()
根窗體呈現(xiàn)示例 -
2.2、tkinter 常用控件
- 常用控件:常用的10 多種凸克,如下:
控件 名稱 作用 Button 按鈕 單擊觸發(fā)事件 Canvas 畫布 繪制圖形或繪制特殊控件 Checkbutton 復選框 多項選擇 Entry 輸入框 接收單行文本輸入 Frame 框架 用于控件分組 Label 標簽 單行文本顯示 Lisbox 列表框 顯示文本列表 Menu 菜單 創(chuàng)建菜單命令 Message 消息 多行文本標簽议蟆,與Label 用法類似 Radiobutton 單選按鈕 從互斥的多個選項中做單項選擇 Scale 滑塊 默認垂直方向,鼠標拖動改變數(shù)值形成可視化交互 Scrollbar 滑動條 默認垂直方向触徐,課鼠標拖動改變數(shù)值咪鲜,可與 Text、Lisbox撞鹉、Canvas等控件配合移動可視化空間 Text 文本框 接收或輸出顯示多行文本 Toplevel 新建窗體容器 在頂層創(chuàng)建新窗體 -
控件的共同屬性:在窗體上呈現(xiàn)的可視化控件疟丙,通常包括尺寸、顏色鸟雏、字體享郊、相對位置、浮雕樣式孝鹊、圖標樣式和懸停光標形狀等共同屬性炊琉。不同的控件由于形狀和功能不同,又有其特征屬性又活。在初始化根窗體和根窗體主循環(huán)之間苔咪,可實例化窗體控件,并設置其屬性柳骄。父容器可為根窗體或其他容器控件實例团赏。常見的控件共同屬性如下表:
屬性 說明 取值 anchor 文本起始位置 CENTER(默認),E,S,W,N,NE,SE,SW,NW bg 背景色 無 bd 加粗(默認 2 像素) 無 bitmap 黑白二值圖標 網(wǎng)上查找 cursor 鼠標懸停光標 網(wǎng)上查找 font 字體 無 fg 前景色 無 height 高(文本控件的單位為行耐薯,不是像素) 無 image 顯示圖像 無 justify 多行文本的對其方式 CENTER(默認)舔清,LEFT,RIGHT,TOP,BOTTOM padx 水平擴展像素 無 pady 垂直擴展像素 無 relief 3D浮雕樣式 FLAT,RAISED,SUNKEN,GROOVE,RIDGE state 控件實例狀態(tài)是否可用 NORMAL(默認),DISABLED width 寬(文本控件的單位為行曲初,不是像素) 無 標簽及常見屬性示例:
from tkinter import * root = Tk() lb = Label(root,text='我是第一個標簽',\ bg='#d3fbfb',\ fg='red',\ font=('華文新魏',32),\ width=20,\ height=2,\ relief=SUNKEN) lb.pack() root.mainloop()
其中体谒,標簽實例lb 在父容器root中實例化,具有代碼中所示的text(文本)臼婆、bg(背景色)抒痒、fg(前景色)、font(字體)颁褂、width(寬评汰,默認以字符為單位)纷捞、height(高,默認以字符為單位)和 relief(浮雕樣式)等一系列屬性被去。
在實例化控件時,實例的屬性可以“屬性=屬性值”的形式枚舉列出奖唯,不區(qū)分先后次序惨缆。例如:“ text='我是第一個標簽' ”顯示標簽的文本內(nèi)容,“bg='#d3fbfb'”設置背景色為十六進制數(shù)RGB色 #d3fbfb等等丰捷。屬性值通常用文本形式表示坯墨。
當然如果這個控件實例只需要一次性呈現(xiàn),也可以不必命名病往,直接實例化并布局呈現(xiàn)出來捣染,例如:Label(root,text='我是第一個標簽',font='華文新魏').pack()
-
屬性 relief 為控件呈現(xiàn)出來的3D浮雕樣式,有 FLAT(平的)停巷、RAISED(凸起的)耍攘、SUNKEN(凹陷的)、GROOVE(溝槽狀邊緣)和 RIDGE(脊狀邊緣) 5種畔勤。
-
2.2蕾各、控件布局
控件的布局通常有pack()
、grid()
和place()
三種方法庆揪。-
2.2.1式曲、pack()方法:是一種簡單的布局方法,如果不加參數(shù)的默認方式缸榛,將按布局語句的先后吝羞,以最小占用空間的方式自上而下地排列控件實例,并且保持控件本身的最小尺寸内颗。如下的例子:
-
用pack() 方法不加參數(shù)排列標簽钧排。為看清楚各控件所占用的空間大小,文本用了不同長度的中英文起暮,并設置relief=GROOVE的凹陷邊緣屬性蹦骑。如下所示:
from tkinter import * root = Tk() lbred = Label(root,text="Red",fg="Red",relief=GROOVE) lbred.pack() lbgreen = Label(root,text="綠色",fg="green",relief=GROOVE) lbgreen.pack() lbblue = Label(root,text="藍",fg="blue",relief=GROOVE) lbblue.pack() root.mainloop()
-
使用pack()方法可設置 fill譬圣、side 等屬性參數(shù)。其中,參數(shù)fill 可取值:fill=X,fill=Y或fill=BOTH司浪,分別表示允許控件向水平方向、垂直方向或二維伸展填充未被占用控件底哥。參數(shù) side 可取值:side=TOP(默認)脉漏,side=LEFT,side=RIGHT,side=BOTTOM,分別表示本控件實例的布局相對于下一個控件實例的方位。如下例子:
用pack()方法加參數(shù)排列標簽from tkinter import * root = Tk() lbred = Label(root,text="Red",fg="Red",relief=GROOVE) lbred.pack() lbgreen = Label(root,text="綠色",fg="green",relief=GROOVE) lbgreen.pack(side=RIGHT) lbblue = Label(root,text="藍",fg="blue",relief=GROOVE) lbblue.pack(fill=X) root.mainloop()
-
用pack() 方法不加參數(shù)排列標簽钧排。為看清楚各控件所占用的空間大小,文本用了不同長度的中英文起暮,并設置relief=GROOVE的凹陷邊緣屬性蹦骑。如下所示:
-
2.2.2颗品、grid()方法:是基于網(wǎng)格的布局肯尺。先虛擬一個二維表格沃缘,再在該表格中布局控件實例。由于在虛擬表格的單元中所布局的控件實例大小不一则吟,單元格也沒有固定或均一的大小槐臀,因此其僅用于布局的定位。pack()方法與grid()方法不能混合使用氓仲。
grid()方法常用布局參數(shù)如下:- column: 控件實例的起始列水慨,最左邊為第0列。
- columnspan: 控件實例所跨越的列數(shù)敬扛,默認為1列晰洒。
- ipadx,ipady: 控件實例所呈現(xiàn)區(qū)域內(nèi)部的像素數(shù),用來設置控件實例的大小啥箭。
- padx,pady: 控件實例所占據(jù)空間像素數(shù)谍珊,用來設置實例所在單元格的大小。
- row: 控件實例的起始行急侥,最上面為第0行砌滞。
- rowspan: 控件實例的起始行數(shù),默認為1行缆巧。
看下面的例子:用grid()方法排列標簽布持,設想有一個3x4的表格,起始行陕悬、列序號均為0.將標簽lbred 至于第2列第0行题暖;將標簽lbgreen置于第0列第1行;將標簽lbblue置于第1列起跨2列第2行捉超,占20像素寬胧卤。
pack()方法排列標簽from tkinter import * root = Tk() lbred = Label(root,text="Red",fg="Red",relief=GROOVE) lbred.grid(column=2,row=0) lbgreen = Label(root,text="綠色",fg="green",relief=GROOVE) lbgreen.grid(column=0,row=1) lbblue = Label(root,text="藍",fg="blue",relief=GROOVE) lbblue.grid(column=1,columnspan=2,ipadx=20,row=2) root.mainloop()
-
2.2.3、place()方法:根據(jù)控件實例在父容器中的絕對或相對位置參數(shù)進行布局拼岳。其常用布局參數(shù)如下:
x,y:控件實例在根窗體中水平和垂直方向上的其實位置(單位為像素)枝誊。注意,根窗體左上角為0,0,水平向右惜纸,垂直向下為正方向叶撒。
relx,rely:控件實例在根窗體中水平和垂直方向上起始布局的相對位置。即相對于根窗體寬和高的比例位置耐版,取值在
0.0~1.0
之間祠够。height,width:控件實例本身的高度和寬度(單位為像素)。
relheight,relwidth:控件實例相對于根窗體的高度和寬度比例粪牲,取值在
0.0~1.0
之間古瓤。-
利用place()方法配合relx,rely和relheight,relwidth參數(shù)所得的到的界面可自適應根窗體尺寸的大小。place()方法與grid()方法可以混合使用。如下例子:利用place()方法排列消息(多行標簽)落君。
place()方法排列消息from tkinter import * root = Tk() root.geometry('320x240') msg1 = Message(root,text='''我的水平起始位置相對窗體 0.2穿香,垂直起始位置為絕對位置 80 像素,我的高度是窗體高度的0.4绎速,寬度是200像素''',relief=GROOVE) msg1.place(relx=0.2,y=80,relheight=0.4,width=200) root.mainloop()
-
-
3皮获、tkinter常見控件的特征屬性
-
3.1、文本輸入和輸出相關控件:文本的輸入與輸出控件通常包括:標簽(Label)朝氓、消息(Message)魔市、輸入框(Entry)、文本框(Text)赵哲。他們除了前述共同屬性外,都具有一些特征屬性和功能君丁。
-
標簽(Label)和 消息(Message):除了單行與多行的不同外枫夺,屬性和用法基本一致,用于呈現(xiàn)文本信息绘闷。值得注意的是:屬性text通常用于實例在第一次呈現(xiàn)時的固定文本橡庞,而如果需要在程序執(zhí)行后發(fā)生變化,則可以使用下列方法之一實現(xiàn):1印蔗、用控件實例的configure()方法來改變屬性text的值扒最,可使顯示的文本發(fā)生變化;2华嘹、先定義一個tkinter的內(nèi)部類型變量var=StringVar() 的值也可以使顯示文本發(fā)生變化吧趣。
看下面的一個例子:制作一個電子時鐘,用root的after()方法每隔1秒time模塊以獲取系統(tǒng)當前時間耙厚,并在標簽中顯示出來强挫。-
方法一:利用configure()方法或config()來實現(xiàn)文本變化。
import tkinter import time def gettime(): timestr = time.strftime("%H:%M:%S") # 獲取當前的時間并轉(zhuǎn)化為字符串 lb.configure(text=timestr) # 重新設置標簽文本 root.after(1000,gettime) # 每隔1s調(diào)用函數(shù) gettime 自身獲取時間 root = tkinter.Tk() root.title('時鐘') lb = tkinter.Label(root,text='',fg='blue',font=("黑體",80)) lb.pack() gettime() root.mainloop()
-
方法二:利用textvariable變量屬性來實現(xiàn)文本變化薛躬。
import tkinter import time def gettime(): var.set(time.strftime("%H:%M:%S")) # 獲取當前時間 root.after(1000,gettime) # 每隔1s調(diào)用函數(shù) gettime 自身獲取時間 root = tkinter.Tk() root.title('時鐘') var=tkinter.StringVar() lb = tkinter.Label(root,textvariable=var,fg='blue',font=("黑體",80)) lb.pack() gettime() root.mainloop()
-
-
文本框(Text):
文本框的常用方法如下:
方法 功能 delete(起始位置俯渤,[,終止位置]) 刪除指定區(qū)域文本 get(起始位置,[,終止位置]) 獲取指定區(qū)域文本 insert(位置型宝,[,字符串]...) 將文本插入到指定位置 see(位置) 在指定位置是否可見文本八匠,返回布爾值 index(標記) 返回標記所在的行和列 mark_names() 返回所有標記名稱 mark_set(標記,位置) 在指定位置設置標記 mark_unset(標記) 去除標記 上表位置的取值可為整數(shù)趴酣,浮點數(shù)或END(末尾)梨树,例如0.0表示第0列第0行
如下一個例子:每隔1秒獲取一次當前日期的時間,并寫入文本框中价卤,如下:本例中調(diào)用 datetime.now()獲取當前日期時間劝萤,用insert()方法每次從文本框txt的尾部(END)開始追加文本。
獲取當前日期的時間并寫入文本中from tkinter import * import time import datetime def gettime(): s=str(datetime.datetime.now())+'\n' txt.insert(END,s) root.after(1000,gettime) # 每隔1s調(diào)用函數(shù) gettime 自身獲取時間 root=Tk() root.geometry('320x240') txt=Text(root) txt.pack() gettime() root.mainloop()
輸入框(Entry):通常作為功能比較單一的接收單行文本輸入的控件慎璧,雖然也有許多對其中文本進行操作的方法床嫌,但通常用的只有取值方法get()和用于刪除文本的delete(起始位置跨释,終止位置),例如:清空輸入框為delete(0厌处,END)鳖谈。
-
-
3.2、按鈕(Button):主要是為響應鼠標單擊事件觸發(fā)運行程序所設的阔涉,故其除控件共有屬性外缆娃,屬性command是最為重要的屬性。通常瑰排,將按鈕要觸發(fā)執(zhí)行的程序以函數(shù)形式預先定義贯要,然后可以用一下兩種方法調(diào)用函數(shù)。Button按鈕的狀態(tài)有:
'normal','active','disabled'
直接調(diào)用函數(shù)椭住。參數(shù)表達式為“command=函數(shù)名”崇渗,注意函數(shù)名后面不要加括號,也不能傳遞參數(shù)京郑。如下面的command=run1:
利用匿名函數(shù)調(diào)用函數(shù)和傳遞參數(shù)宅广。參數(shù)的表達式為“command=lambda”:函數(shù)名(參數(shù)列表)。例如下面的:"command=lambda:run2(inp1.get(),inp2.get())"些举。
-
看下面的例子:1.從兩個輸入框去的輸入文本后轉(zhuǎn)為浮點數(shù)值進行加法運算跟狱,要求每次單擊按鈕產(chǎn)生的算是結(jié)果以文本的形式追加到文本框中,將原輸入框清空户魏。2.按鈕方法一不傳參數(shù)調(diào)用函數(shù)run1()實現(xiàn)驶臊,按鈕“方法二”用lambda調(diào)用函數(shù)run2(x,y)同時傳遞參數(shù)實現(xiàn)。
簡單加法器from tkinter import * def run1(): a = float(inp1.get()) b = float(inp2.get()) s = '%0.2f+%0.2f=%0.2f\n' % (a, b, a + b) txt.insert(END, s) # 追加顯示運算結(jié)果 inp1.delete(0, END) # 清空輸入 inp2.delete(0, END) # 清空輸入 def run2(x, y): a = float(x) b = float(y) s = '%0.2f+%0.2f=%0.2f\n' % (a, b, a + b) txt.insert(END, s) # 追加顯示運算結(jié)果 inp1.delete(0, END) # 清空輸入 inp2.delete(0, END) # 清空輸入 root = Tk() root.geometry('460x240') root.title('簡單加法器') lb1 = Label(root, text='請輸入兩個數(shù)绪抛,按下面兩個按鈕之一進行加法計算') lb1.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.1) inp1 = Entry(root) inp1.place(relx=0.1, rely=0.2, relwidth=0.3, relheight=0.1) inp2 = Entry(root) inp2.place(relx=0.6, rely=0.2, relwidth=0.3, relheight=0.1) # 方法-直接調(diào)用 run1() btn1 = Button(root, text='方法一', command=run1) btn1.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1) # 方法二利用 lambda 傳參數(shù)調(diào)用run2() btn2 = Button(root, text='方法二', command=lambda: run2(inp1.get(), inp2.get())) btn2.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1) # 在窗體垂直自上而下位置60%處起资铡,布局相對窗體高度40%高的文本框 txt = Text(root) txt.place(rely=0.6, relheight=0.4) root.mainloop()
-
3.3、單選按鈕:(Radiobutton)是為了響應故鄉(xiāng)排斥的若干單選項的單擊事件以觸發(fā)運行自定義函數(shù)所設的幢码,該控件排除具有共有屬性外笤休,還具有顯示文本(text)、返回變量(variable)症副、返回值(value)店雅、響應函數(shù)名(command)等重要屬性。響應函數(shù)名“command=函數(shù)名”的用法與Button相同贞铣,函數(shù)名最后也要加括號闹啦。返回變量variable=var通常應預先聲明變量的類型var=IntVar()或var=StringVar(),在所調(diào)用的函數(shù)中方可用var.get()方法獲取被選中實例的value值。例如下面:
單選按鈕from tkinter import * def Mysel(): dic = {0:'甲',1:'乙',2:'丙'} s = "您選了" + dic.get(var.get()) + "項" lb.config(text = s) root = Tk() root.title('單選按鈕') lb = Label(root) lb.pack() var = IntVar() rd1 = Radiobutton(root,text="甲",variable=var,value=0,command=Mysel) rd1.pack() rd2 = Radiobutton(root,text="乙",variable=var,value=1,command=Mysel) rd2.pack() rd3 = Radiobutton(root,text="丙",variable=var,value=2,command=Mysel) rd3.pack() root.mainloop()
-
3.4辕坝、復選框:(Checkbutton) 是為了返回多個選項值的交互控件窍奋,通常不直接觸發(fā)函數(shù)的執(zhí)行。該控件除具有共有屬性外,還具有顯示文本(text)琳袄、返回變量(variable)江场、選中返回值(onvalue)和未選中默認返回值(offvalue)等重要屬性。返回變量variable=var 通辰讯海可以預先逐項分別聲明變量的類型var=IntVar() (默認)或 var=StringVar(), 在所調(diào)用的函數(shù)中方可分別調(diào)用 var.get()方法 取得被選中實例的 onvalue或offvalue值址否。復選框?qū)嵗ǔ_€可分別利用 select()、deselect()和 toggle() 方法對其進行選中碎紊、清除選中和反選操作佑附。
-
如下的例子: 利用復選框?qū)崿F(xiàn),單擊OK仗考,可以將選中的結(jié)果顯示在標簽上音同。效果如下:
復選框的應用-
方法:利用函數(shù)中的 if-else 分支實現(xiàn)多項顯示
from tkinter import * import tkinter def run(): if(CheckVar1.get()==0 and CheckVar2.get()==0 and CheckVar3.get()==0 and CheckVar4.get()==0): s = '您還沒選擇任何愛好項目' else: s1 = "足球" if CheckVar1.get()==1 else "" s2 = "籃球" if CheckVar2.get() == 1 else "" s3 = "游泳" if CheckVar3.get() == 1 else "" s4 = "田徑" if CheckVar4.get() == 1 else "" s = "您選擇了%s %s %s %s" % (s1,s2,s3,s4) lb2.config(text=s) root = tkinter.Tk() root.title('復選框') lb1=Label(root,text='請選擇您的愛好項目') lb1.pack() CheckVar1 = IntVar() CheckVar2 = IntVar() CheckVar3 = IntVar() CheckVar4 = IntVar() ch1 = Checkbutton(root,text='足球',variable = CheckVar1,onvalue=1,offvalue=0) ch2 = Checkbutton(root,text='籃球',variable = CheckVar2,onvalue=1,offvalue=0) ch3 = Checkbutton(root,text='游泳',variable = CheckVar3,onvalue=1,offvalue=0) ch4 = Checkbutton(root,text='田徑',variable = CheckVar4,onvalue=1,offvalue=0) ch1.pack() ch2.pack() ch3.pack() ch4.pack() btn = Button(root,text="OK",command=run) btn.pack() lb2 = Label(root,text='') lb2.pack() root.mainloop()
-
-
-
3.5、列表框 與 組合框:
- 3.5.1秃嗜、列表框:(Listbox) 可供用戶單選或多選所列條目以形成人機交互瘟斜。列表框控件的主要方法見下面的表:
方法 功能描述 curselection() 返回光標選中項目編號的元組,注意并不是單個的整數(shù) delete(起始位置痪寻,終止位置) 刪除項目,終止位置可省略虽惭,全部清空為delete(0,END) get(起始位置橡类,終止位) 返回范圍所含項目文本的元組,終止位置可忽略 insert(位置芽唇,項目元素) 插入項目元素(若有多項顾画,可用列表或元組類型賦值),若位置為END匆笤,則將項目元素添加在最后 size() 返回列表框行數(shù) 執(zhí)行自定義函數(shù)時研侣,通常使用“實例名.surselection()” 或 “selected” 來獲取選中項的位置索引。由于列表框?qū)嵸|(zhì)上就是將Python 的列表類型數(shù)據(jù)可視化呈現(xiàn)炮捧,在程序?qū)崿F(xiàn)時庶诡,也可直接對相關列表數(shù)據(jù)進行操作,然后再通過列表框展示出來咆课,而不必拘泥于可視化控件的方法末誓。看下面的一個例子:實現(xiàn)列表框的初始化书蚪、添加喇澡、插入、修改殊校、刪除和清空操作晴玖,如下:
列表框的應用from tkinter import * def ini(): Lstbox1.delete(0,END) list_items = ["數(shù)學","物理","化學","語文","外語"] for item in list_items: Lstbox1.insert(END,item) def clear(): Lstbox1.delete(0,END) def ins(): if entry.get() != '': if Lstbox1.curselection() == (): Lstbox1.insert(Lstbox1.size(),entry.get()) else: Lstbox1.insert(Lstbox1.curselection(),entry.get()) def updt(): if entry.get() != '' and Lstbox1.curselection() != (): selected=Lstbox1.curselection()[0] Lstbox1.delete(selected) Lstbox1.insert(selected,entry.get()) def delt(): if Lstbox1.curselection() != (): Lstbox1.delete(Lstbox1.curselection()) root = Tk() root.title('列表框?qū)嶒?) root.geometry('320x240') frame1 = Frame(root,relief=RAISED) frame1.place(relx=0.0) frame2 = Frame(root,relief=GROOVE) frame2.place(relx=0.5) Lstbox1 = Listbox(frame1) Lstbox1.pack() entry = Entry(frame2) entry.pack() btn1 = Button(frame2,text='初始化',command=ini) btn1.pack(fill=X) btn2 = Button(frame2,text='添加',command=ins) btn2.pack(fill=X) btn3 = Button(frame2,text='插入',command=ins) # 添加和插入功能實質(zhì)上是一樣的 btn3.pack(fill=X) btn4 = Button(frame2,text='修改',command=updt) btn4.pack(fill=X) btn5 = Button(frame2,text='刪除',command=delt) btn5.pack(fill=X) btn6 = Button(frame2,text='清空',command=clear) btn6.pack(fill=X) root.mainloop()
-
3.5.2、組合框:(Combobox) 實質(zhì)上是帶文本框的上拉列表框,其功能也將是Python 的列表類型數(shù)據(jù)可視化呈現(xiàn)呕屎,并提供用戶單選或多選所列條目以形成人機交互让簿。在圖形化界面設計時,由于其具有靈活的界面榨惰,因此往往比列表框更受喜愛拜英。但該控件并不包含在 tkinter 模塊中,而是與 TreeView琅催、Progressbar居凶、Separator等控件一同包含在tkinter 的子模塊ttk中。如果使用該控件藤抡,應先與from tkinter import ttk 語句引用ttk子模塊侠碧,然后創(chuàng)建組合框?qū)嵗?
實例名=Combobox(根對象,[屬性列表])
指定變量var=StringVar(),并設置實例屬性 textvariable = var,values=[列表...]。組合框控件常用方法有:獲得所選中的選項值get()和獲得所選中的選項索引current()缠黍。
看下面的一個例子:實現(xiàn)四則運算計算器弄兜,將兩個操作數(shù)分別填入兩個文本框后,通過選擇組合框中的算法觸發(fā)運算瓷式,如下:
組合框的應用from tkinter.ttk import * def calc(event): a = float(t1.get()) b = float(t2.get()) dic = {0:a+b,1:a-b,2:a*b,3:a/b} c = dic[comb.current()] lbl.config(text=str(c)) root = Tk() root.title('四則運算') root.geometry('320x240') t1 = Entry(root) t1.place(relx=0.1,rely=0.1,relwidth=0.2,relheight=0.1) t2 = Entry(root) t2.place(relx=0.5,rely=0.1,relwidth=0.2,relheight=0.1) var = StringVar() comb = Combobox(root,textvariable=var,values=['加','減','乘','除',]) comb.place(relx=0.1,rely=0.5,relwidth=0.2) comb.bind('<<ComboboxSelected>>',calc) lbl=Label(root,text='結(jié)果') lbl.place(relx=0.5,rely=0.7,relwidth=0.2,relheight=0.3) root.mainloop()
-
3.6替饿、滑塊:(Scale) 是一種 直觀地進行數(shù)值輸入的交互控件,其主要屬性見下表:
屬性 功能描述 from_ 起始值(最小可取值) lable 標簽文字贸典,默認為無 length 滑塊控件實例寬(水平方向)或 高(垂直方向)视卢,默認為100像素 orient 滑塊控件實例呈現(xiàn)方向,VERTCAL或HORIZONTAL(默認) repeatdelay 鼠標響應延時廊驼,默認為 300ms resolution 分辨精度据过,即最小值間隔 sliderlength 滑塊寬度,默認為30 像素 state 狀態(tài)妒挎,若設置 state=DISABLED,則滑塊控件實例不可用 tickinterval 標尺間隔绳锅,默認為0,若設置過小酝掩,則會重疊 to 終止值(最大可取值) variable 返回數(shù)值類型鳞芙,可為IntVar(整數(shù))、DoubleVar(浮點數(shù))庸队、或 StringVar(字符串) width 控件實例本身的寬度积蜻,默認為15像素 滑塊控件實例的主要方法比較簡單,有 get()和set(值)彻消,分別為取值和將滑塊設在某特定值上竿拆。滑塊實例也可綁定鼠標左鍵釋放事件<ButtoonRelease-1>,并在執(zhí)行函數(shù)中添加參數(shù)event來實現(xiàn)事件響應宾尚。
例如:在一個窗體上設計一個200像素寬的水平滑塊丙笋,取值范圍為1.0~5.0谢澈,分辨精度為0.05,刻度間隔為 1御板,用鼠標拖動滑塊后釋放鼠標可讀取滑塊值并顯示在標簽上锥忿。效果如下:
滑塊控件的應用from tkinter import * def show(event): s = '滑塊的取值為' + str(var.get()) lb.config(text=s) root = Tk() root.title('滑塊實驗') root.geometry('320x180') var=DoubleVar() scl = Scale(root,orient=HORIZONTAL,length=200,from_=1.0,to=5.0,label='請拖動滑塊',tickinterval=1,resolution=0.05,variable=var) scl.bind('<ButtonRelease-1>',show) scl.pack() lb = Label(root,text='') lb.pack() root.mainloop()
-
3.7、菜單:(Menu)用于可視化地為一系列的命令分組怠肋,從而方便用戶找到和觸發(fā)執(zhí)行這些命令敬鬓。這里Menu所實例化別的主要是菜單,其通式為:
菜單實例名=Menu(根窗體) 菜單分組1=Menu(菜單實例名) 菜單實例名.add_cascade(<label=菜單分組1 顯示文本>,<menu=菜單分組1>) 菜單分組1.add_command(<label=命令1文本>,<command=命令1函數(shù)名>)
其中較為常見的方法有:add_cascade()笙各、add_command()和add_separator()钉答,分別用于添加一個菜單分組、添加一條菜單命令和添加一條分割線杈抢。
利用Menu控件也可以創(chuàng)建快捷菜單(又稱為上下文菜單)数尿。通常需要右擊彈出的控件實例綁定鼠標右擊響應事件<Button-3>,并指向一個捕獲event參數(shù)的自定義函數(shù),在該自定義函數(shù)中惶楼,將鼠標的觸發(fā)位置event.x_root 和 event.y_root以post()方法傳給菜單右蹦。
例子:仿照window自帶的“記事本”中的文件和編輯 菜單,實現(xiàn)在主菜單個快捷菜單上觸發(fā)菜單命令歼捐,并相應改變窗體上的標簽的文本內(nèi)容何陆。效果如下:
菜單和快捷菜單from tkinter import * def new(): s = '新建' lb1.config(text=s) def ope(): s = '打開' lb1.config(text=s) def sav(): s = '保存' lb1.config(text=s) def cut(): s = '剪切' lb1.config(text=s) def cop(): s = '復制' lb1.config(text=s) def pas(): s = '粘貼' lb1.config(text=s) def popupmenu(event): mainmenu.post(event.x_root,event.y_root) root = Tk() root.title('菜單實驗') root.geometry('320x240') lb1 = Label(root,text='顯示信息',font=('黑體',32,'bold')) lb1.place(relx=0.2,rely=0.2) mainmenu = Menu(root) menuFile = Menu(mainmenu) # 菜單分組 menuFile mainmenu.add_cascade(label="文件",menu=menuFile) menuFile.add_command(label="新建",command=new) menuFile.add_command(label="打開",command=ope) menuFile.add_command(label="保存",command=sav) menuFile.add_separator() # 分割線 menuFile.add_command(label="退出",command=root.destroy) menuEdit = Menu(mainmenu) # 菜單分組 menuEdit mainmenu.add_cascade(label="編輯",menu=menuEdit) menuEdit.add_command(label="剪切",command=cut) menuEdit.add_command(label="復制",command=cop()) menuEdit.add_command(label="粘貼",command=pas()) root.config(menu=mainmenu) root.bind('Button-3',popupmenu) # 根窗體綁定鼠標右擊響應事件 root.mainloop()
-
3.8、子窗體:用Toplevel可新建一個顯示在最前面的子窗體豹储,其通式為:
字體實例名=Toplevel(根窗體)
甲献,子窗體與根窗體類似,也可設置title颂翼、geomerty等屬性,并在畫布上布局其他控件慨灭。如下的例子:在根窗體上創(chuàng)建菜單朦乏,觸發(fā)創(chuàng)建一個新的窗體
根窗體與子窗體from tkinter import * def newwind(): winNew = Toplevel(root) winNew.geometry('320x240') winNew.title('新窗體') lb2 = Label(winNew,text='我在新窗體上') lb2.place(relx=0.2,rely=0.2) btClose=Button(winNew,text='關閉',command=winNew.destroy) btClose.place(relx=0.7,rely=0.5) root = Tk() root.title('新建窗體實驗') root.geometry('320x240') lb1 = Label(root,text='主窗體',font=('黑體',32,'bold')) lb1.place(relx=0.2,rely=0.2) mainmenu = Menu(root) menuFile = Menu(mainmenu) mainmenu.add_cascade(label='菜單',menu=menuFile) menuFile.add_command(label='新窗體',command=newwind) menuFile.add_separator() menuFile.add_command(label='退出',command=root.destroy) root.config(menu=mainmenu) root.mainloop()
關閉窗體程序運行的方法通常用 destory(),而不建議用 quit()。用Toplevel 所創(chuàng)建的子窗體是非模式(Modeless)的窗體氧骤,雖然初建時子窗體在最前面呻疹,但根窗體上的控件實例也是可以被操作的。
-
3.9筹陵、模式對話框(Modal):是相對于前面介紹的非模式窗體而言的刽锤,所彈出的對話框必須應答,在關閉之前無法操作其后面的其他窗體朦佩。常見的模式對話框有消息對話框并思、輸入對話框、文件選擇對話框语稠、顏色選擇對話框等宋彼。
-
3.9.1弄砍、交互對話框
(一)、消息對話框: 引用 tkinter.messagebox 包输涕,可使用消息對話框函數(shù)音婶。執(zhí)行這些函數(shù),可彈出模式消息對話框莱坎,并根據(jù)用戶的響應但會一個布爾值衣式。其通式為:
消息對話框函數(shù)(<title=標題文本>,<message=消息文本>,[其他參數(shù)])
看下面的例子:單擊按鈕,彈出確認取消對話框檐什,并將用戶回答顯示在標簽中碴卧。效果如下:
確定取消對話框from tkinter import * import tkinter.messagebox def xz(): answer=tkinter.messagebox.askokcancel('請選擇','請選擇確定或取消') if answer: lb.config(text='已確認') else: lb.config(text='已取消') root = Tk() lb = Label(root,text='') lb.pack() btn=Button(root,text='彈出對話框',command=xz) btn.pack() root.mainloop()
(二)、輸入對話框: 引用tkinter.simpledialog包厢汹,可彈出輸入對話框螟深,用以接收用戶的簡單輸入。輸入對話框常用 askstring()烫葬、askfloat()和askfloat() 三種函數(shù)界弧,分別用于接收字符串、整數(shù)和浮點數(shù)類型的輸入搭综。
如下面的例子:單擊按鈕垢箕,彈出輸入對話框,接收文本輸入顯示在窗體的標簽上兑巾。如下:
輸入對話框from tkinter.simpledialog import * def xz(): s=askstring('請輸入','請輸入一串文字') lb.config(text=s) root = Tk() lb = Label(root,text='') lb.pack() btn=Button(root,text='彈出輸入對話框',command=xz) btn.pack() root.mainloop()
-
3.9.2条获、文件選擇對話框:引用tkinter.filedialog包,可彈出文件選擇對話框蒋歌,讓用戶直觀地選擇一個或一組文件帅掘,以供進一步的文件操作。常用的文件選擇對話框函數(shù)有 askopenfilename()堂油、askopenfilenames()和asksaveasfilename(),分別用于進一步打開一個文件修档、一組文件和保存文件。其中府框,askopenfilename()和asksaveasfilenamme()函數(shù)的返回值類型為包含文件路徑的文件名字符串吱窝,而askopenfilenames()函數(shù)的返回值類型為元組。
例如:單擊按鈕迫靖,彈出文件選擇對話框(“打開”對話框)院峡,并將用戶所選擇的文件路徑和文件名顯示在窗體的標簽上。如下
文件選擇對話框from tkinter import * import tkinter.filedialog def xz(): filename=tkinter.filedialog.askopenfilename() if filename != '': lb.config(text='您選擇的文件是'+filename) else: lb.config(text='您沒有選擇任何文件') root = Tk() lb = Label(root,text='') lb.pack() btn=Button(root,text='彈出文件選擇對話框',command=xz) btn.pack() root.mainloop()
-
3.9.3系宜、顏色選擇對話框:引用tkinter.colorchooser包照激,可使用 askcolor()函數(shù)彈出模式顏色選擇對話框,讓用戶可以個性化地設置顏色屬性盹牧。該函數(shù)的返回形式為包含RGB十進制浮點元組和RGB十六進制字符串的元組類型实抡,例如:“((135.527343.52734375,167.65234375,186.7265625)),'#87a7ba'”欠母。通常,可將其轉(zhuǎn)換為字符串類型后吆寨,再截取以十六進制數(shù)表示的RGB顏色字符串用于為屬性賦值赏淌。
舉例:單擊按鈕,彈出顏色選擇對話框啄清,并將用戶所選擇的顏色設置為窗體上標簽的背景顏色六水,如下:
顏色選擇對話框from tkinter import * import tkinter.colorchooser def xz(): color=tkinter.colorchooser.askcolor() colorstr=str(color) print('打印字符串%s 切掉后=%s' % (colorstr,colorstr[-9:-2])) lb.config(text=colorstr[-9:-2],background=colorstr[-9:-2]) root = Tk() lb = Label(root,text='請關注顏色的變化') lb.pack() btn=Button(root,text='彈出顏色選擇對話框',command=xz) btn.pack() root.mainloop()
-
-
-
4、事件響應
用tkinter 可將用戶事件與自定義函數(shù)綁定辣卒,用鍵盤或鼠標的動作事件來響應觸發(fā)自定義函數(shù)的執(zhí)行掷贾。其通式為:控件實例.bind(<事件代碼>,<函數(shù)名>)
其中,事件代碼通常以半角小于號“<”和大于號“>” 界定荣茫,包括事件和按鍵等 2~3個部分想帅,它們之間用減號分隔,常見事件代碼見下表:
事件 事件代碼 備注 單擊鼠標左鍵 <ButtonPress-1> 可簡寫為<Button-1> 或 <1> 單擊鼠標中鍵 <ButtonPress-2> 可簡寫為<Button-2> 或 <2> 單擊鼠標右鍵 <ButtonPress-3> 可簡寫為<Button-3> 或 <3> 釋放鼠標左鍵 <ButtonRelease-1> --- 釋放鼠標中鍵 <ButtonRelease-2> --- 釋放鼠標右鍵 <ButtonRelease-3> --- 按住鼠標左鍵移動 <B1-Motion> --- 按住鼠標中鍵移動 <B2-Motion> --- 按住鼠標右鍵移動 <B3-Motion> --- 轉(zhuǎn)動鼠標滾輪 <MouseWheel> --- 雙擊鼠標左鍵 <Double-Button-1> --- 鼠標進入控件實例 <Enter> 注意與回車事件的區(qū)別 鼠標離開控件實例 <Leave> --- 鍵盤任意鍵 <Key> --- 字母和數(shù)字 < Key-字母>,例如<key-a>啡莉、<Key-A> 簡寫不帶小于和大于號,例如:a,A和1等 回車 <Return> <Tab>,<Shift>,<Control>(注意不能用<Ctrl>),<Alt>等類同 空格 <Space> --- 方向鍵 <Up> ,<Down>,<Left>,<Right> --- 功能鍵 <Fn>例如:<F1>等 --- 組合鍵 鍵名之間以減號鏈接,例如<Control-k>,<Shift-6>,<Alt-Up>等 注意大小寫 例如,將框架控件實例frame 綁定鼠標右鍵單擊事件,調(diào)用自定義函數(shù) myfunc()可表示為"
frame.bind('<Button-3>',myfunc)
",注意: myfunc后面沒有括號港准。將控件實例綁定到鍵盤事件和部分光標不落在具體控件實例上的鼠標事件時,還需要設置該實例執(zhí)行focus_set() 方法獲得焦點咧欣,才能對事件持續(xù)響應浅缸。例如: frame.focus_set()。所調(diào)用的自定義函數(shù)若需要利用鼠標或鍵盤的響應值魄咕,可將event作為參數(shù)衩椒,通過event的屬性獲取。event的屬性見下表:event屬性 意義 x或y(注意是小寫) 相對于事件綁定控件實例左上角的坐標值(像素) root_x或root_y(注意是小寫) 相對于顯示屏幕左上角的坐標值(像素) char 可顯示的字符哮兰,若按鍵不可顯示毛萌,則返回為空字符串 keysysm 字符或字符型按鍵名,如:“a”或“Escape” keysysm_num 按鍵的十進制 ASCII 碼值 例如:將標簽綁定鍵盤任意鍵觸發(fā)事件并獲取焦點喝滞,并將按鍵字符顯示在標簽上
響應鍵盤事件from tkinter import * def show(event): s=event.keysym lb.config(text=s) root=Tk() root.title('按鍵實驗') root.geometry('200x200') lb=Label(root,text='請按鍵',font=('黑體',48)) lb.bind('<Key>',show) lb.focus_set() lb.pack() root.mainloop()