本節(jié)知識(shí)大綱: 本節(jié)知識(shí)框架 Python里的圖形化界面(GUI)模塊主要有Tkinter(python自帶)、PyQt、wxPython,我們這節(jié)主要講解Tkinter組件: 一、Tkinter介紹tkinter模塊只要用戶安裝好Python環(huán)境就可以直接使用; 1. 第一個(gè)tkinter程序import tkinter as tk # 給tkinter重命名為tkroot = tk.Tk() # 新建一個(gè)窗體root.mainloop() # 展示窗體 2. 設(shè)置屬性并添加控件設(shè)置窗體標(biāo)題、指定窗體大小、添加按鈕、輸入框、標(biāo)簽并布局
二、控件的屬性1. tkinter常用的控件屬性(1)定義控件的名稱使用參數(shù)text,傳入的字符串值即為控件的名稱; (2)定義控件高度使用參數(shù)hight,寬度使用參數(shù)width,傳入的值為整形數(shù)值; (3)定義控件在空間中的位置,使用參數(shù)anchor,傳入的字符參數(shù)為e、s、w、n以地圖的東南西北來定義為右下左上,也可以同時(shí)設(shè)置左下sw、左上nw、右下se、右上ne; (4)定義控件的背景色,使用參數(shù)bg,前景色使用參數(shù)fg,傳入字符值可以直接是對(duì)應(yīng)顏色的英文名稱; (5)設(shè)置布局在pack()函數(shù)里,使用參數(shù)side,傳入的值為常量tk.LEFT或者tk.RIGHT,表示從左到右或者從右到左布局 (6)創(chuàng)建圖片控件時(shí),圖片控件的文件源使用參數(shù)file,傳入的字符值為為文件路徑,在控件中使用圖片則使用參數(shù)image,傳入的值為圖片控件變量; (7)設(shè)置整個(gè)窗體的尺寸,使用參數(shù)geometry,傳入的值為字符值,注意乘號(hào)用小寫字母x代替;如果要設(shè)置長(zhǎng)400寬300的窗體則使用語句geometry = '400x300' (8)設(shè)置控件與邊界的距離在pack函數(shù)里使用參數(shù)padx,設(shè)置左右距離;使用pady設(shè)置上下距離。 2. 案例演示:畫出一個(gè)簡(jiǎn)單的窗體布局import tkinter as tk# 新建一個(gè)窗體名稱:rootroot = tk.Tk()# 為窗體添加一個(gè)標(biāo)題root.title('第二個(gè)Python窗體')# 新建標(biāo)簽photo = tk.PhotoImage(file = '/Users/yushengtan/Desktop/image.png')Label01 = tk.Label(root,text = '第一個(gè)Label標(biāo)簽',anchor = 'se').pack(side = tk.LEFT)imageLable01 = tk.Label(root,image = photo).pack(side = tk.LEFT)Label02 = tk.Label(root,text = '第二個(gè)Label標(biāo)簽',bg = 'blue',fg = 'white',font = ('華文宋體',20)).pack()Label03 = tk.Label(root,text = '第三個(gè)Label標(biāo)簽',).pack()Label04 = tk.Label(root,text = '第四個(gè)Label標(biāo)簽').pack()Label05 = tk.Label(root,text = '第五個(gè)Label標(biāo)簽').pack()Button01 = tk.Button(root,text = '確定').pack()# 顯示root.mainloop() 效果演示: 簡(jiǎn)單窗體布局 3. 案例演示:畫出能計(jì)算加法的計(jì)算器界面
界面效果: 三、基本布局1. place絕對(duì)布局pack布局是按順序布局,而place布局可以直接定義絕對(duì)位置,只需要給place()函數(shù)里傳入兩個(gè)參數(shù)x和y,其值為整型數(shù)值表示相對(duì)于窗體左上角的坐標(biāo)位置;用法:place(x=10,y=20) 案例演示:繪制一個(gè)簡(jiǎn)易的登錄界面 from tkinter import *root = Tk()root.title('用戶登錄')root.geometry('400x180')Label_username = Label(root,text = '登錄名:',font = ('華為黑體',16)).place(x = 50,y = 20)Entry_username = Entry(root,font = ('華文黑體',16),width = 20).place(x = 120,y = 20)Label_password = Label(root,text = '密 碼:',font = ('華為黑體',16)).place(x = 50,y = 60)Entry_password = Entry(root,font = ('華文黑體',16),width = 20).place(x = 120,y = 60)Button_login = Button(root,text = '登錄',font = ('華文黑體',16),width = 8).place(x = 70,y = 120)Button_cancer = Button(root,text = '取消',font = ('華文黑體',16),width = 8).place(x = 210,y = 120)root.mainloop() 運(yùn)行效果:2. grid表格布局grid是一種網(wǎng)格布局,grid(row = 1,column = 2),n行n列分別表示表格的行數(shù)和列數(shù),從0開始計(jì)數(shù);可以使用參數(shù)sticky控制控件靠近單元格的位置,字符值可以給出n、s、w、e設(shè)置上、下、左、右,我們還是以登錄窗體為例:
輸出效果:
四、使用類封裝GUI這里我們使用類來封裝GUI程序,以至于我們后面需要調(diào)用的時(shí)候直接實(shí)例化一個(gè)對(duì)象就可以產(chǎn)生一個(gè)窗口,類與對(duì)象的知識(shí)我們后面會(huì)深入講解,現(xiàn)在我們只需怎么使用即可;我們把前面的登錄窗口通過類來進(jìn)行封裝 from tkinter import *class login_GUI(object): def __init__(self): ''' 窗體的構(gòu)造函數(shù),用來做界面的初始化,GUI代碼放在此函數(shù)中 ''' self.frame = Tk() self.frame.title('登錄窗體') self.frame.geometry('400x160') self.photo = PhotoImage(file='/Users/yushengtan/Desktop/login.png') imgLabel = Label(self.frame, image=self.photo).grid(row=0, column=0, rowspan=2) # 第一行 第一列 Label_username = Label(self.frame, text='用戶名:', font=('微軟雅黑', 14)).grid(row=0, column=1) # 第一行 第二列 Entry_username = Entry(self.frame, font=('華文黑體', 16)).grid(row=0, column=2) # 第二行 第二列 Label_password = Label(self.frame, text='密 碼:', font=('華文黑體', 16)).grid(row=1, column=1) # 第二行 第三列 Entry_password = Entry(self.frame, font=('華文黑體', 16)).grid(row=1, column=2) # 第四行 第二列 Button_login = Button(self.frame, text='登錄', width=8, font=('華文黑體', 16)).grid(row=3, column=2, sticky='e') # 第四行 第三列 Button_cancer = Button(self.frame, text='取消', width=8, font=('華文黑體', 16)).grid(row=3, column=2, sticky='w') def run(self): self.frame.mainloop()if __name__ == '__main__': # 由窗體的模板實(shí)例化一個(gè)具體的登錄窗體 this_login = login_GUI() # 展示窗體 this_login.run() 五、響應(yīng)事件以上我們實(shí)現(xiàn)了GUI界面的設(shè)計(jì),加法計(jì)算器、登錄窗口,但是沒有程序并不能工作,如果想要程序工作起來還得給控件設(shè)置響應(yīng)事件;事件是什么呢?事件就是響應(yīng)某一個(gè)動(dòng)作,如點(diǎn)擊某一個(gè)按鈕、輸入鍵盤的某一個(gè)鍵等等。我們現(xiàn)在來完善前面設(shè)計(jì)加法計(jì)算器,讓其能真正做加法計(jì)算; 1. 完成點(diǎn)擊按鈕響應(yīng)事件的步驟(1)完成時(shí)間的功能---函數(shù) (2)把功能捆綁到按鈕上,添加command參數(shù),其值為功能函數(shù)名,注意沒有小括號(hào),這一點(diǎn)非常重要,很多時(shí)候出錯(cuò)了,都不知道錯(cuò)在哪了,就是因?yàn)椴恍⌒募恿死ㄌ?hào)! 注意:取出文本框的數(shù)值可以使用get()方法,設(shè)置文本框的數(shù)值可以使用set()方法;控件基本屬性的設(shè)定和控件的布局語句要分開; 2. 案例:實(shí)現(xiàn)兩數(shù)相加的功能通過響應(yīng)事件完成加法計(jì)算器
運(yùn)行效果: 3. 案例:實(shí)現(xiàn)用戶登錄功能需求: (1)如果用戶名為admin,密碼為123.com,顯示登錄成功! (2)如果用戶名不對(duì),顯示用戶名不存在; (3)如果密碼不對(duì),顯示密碼錯(cuò)誤,如果錯(cuò)誤三次,提示:賬號(hào)已鎖定。 提示:實(shí)現(xiàn)窗體的關(guān)閉,可以使用方法self.frame.destory()關(guān)閉窗體; # 用戶登錄from tkinter import *from tkinter.messagebox import *class login_GUI(object): def __init__(self): ''' 窗體的構(gòu)造函數(shù),用來做界面的初始化,GUI代碼放在此函數(shù)中 ''' self.frame = Tk() self.frame.title('登錄窗體') self.frame.geometry('400x160') self.photo = PhotoImage(file='/Users/yushengtan/Desktop/login.png') self.imgLabel = Label(self.frame, image=self.photo) self.imgLabel.grid(row=0, column=0, rowspan=2) # 第一行 第一列 self.Label_username = Label(self.frame, text='用戶名:', font=('微軟雅黑', 14)) self.Label_username.grid(row=0, column=1) # 第一行 第二列 self.Entry_username = Entry(self.frame, font=('華文黑體', 16)) self.Entry_username.grid(row=0, column=2) # 第二行 第二列 self.Label_password = Label(self.frame, text='密 碼:', font=('華文黑體', 16)) self.Label_password.grid(row=1, column=1) # 第二行 第三列 self.Entry_password = Entry(self.frame, font=('華文黑體', 16)) self.Entry_password.grid(row=1, column=2) # 第四行 第二列 self.Button_login = Button(self.frame, text='登錄', width=8, font=('華文黑體', 16),command = self.login) self.Button_login.grid(row=3, column=2, sticky='e') # 第四行 第三列 self.Button_cancer = Button(self.frame, text='取消', width=8, font=('華文黑體', 16),command = self.cancer) self.Button_cancer.grid(row=3, column=2, sticky='w') # 定義全局變量 self.password_error_times = 0 self.is_disable = False def run(self): self.frame.mainloop() def login(self): # 【1】先獲取用戶名和密碼 username = str(self.Entry_username.get()) password = str(self.Entry_password.get()) # 【2】驗(yàn)證 if username.strip().lower() != 'admin': showinfo('系統(tǒng)消息','用戶名不存在,請(qǐng)核實(shí)后再登錄!') elif password.strip() != '123.com': self.password_error_times += 1 # 判斷是否達(dá)到三次 if self.password_error_times >= 3: self.is_disable = True # 判斷禁用標(biāo)志 if self.is_disable: showinfo('系統(tǒng)消息','密碼輸入錯(cuò)誤已達(dá)三次,賬號(hào)已鎖定,請(qǐng)聯(lián)系管理員') else: showinfo('系統(tǒng)消息', '密碼錯(cuò)誤!') else: showinfo('系統(tǒng)消息','登錄成功') # 如果在3次以內(nèi)輸入正確,則錯(cuò)誤次數(shù)計(jì)數(shù)歸零 self.password_error_times = 0 def cancer(self): # 實(shí)現(xiàn)窗體的關(guān)閉 self.frame.destroy()if __name__ == '__main__': # 由窗體的模板實(shí)例化一個(gè)具體的登錄窗體 this_login = login_GUI() # 展示窗體 this_login.run() 演示效果: 六、GUI擴(kuò)展功能1. ttk模塊ttk模塊是對(duì)傳統(tǒng)tkinter模塊的增強(qiáng),傳統(tǒng)的tkinter模塊界面比較單一,控件種類有限,界面布局邏輯性差。ttk模塊是tkinter下的一個(gè)子模塊,它的界面比tkinter更豐富更美觀。ttk的用法同tkinter大體相同,但是有一些屬性ttk不再支持,而tkinter中的fg、bg、font屬性在ttk中不再被支持,取而代之的是style對(duì)象; 2. 復(fù)選框Checkbutton
演示效果: 3. 單選框Radiobutton# RadioButtonfrom tkinter import *# from tkinter.ttk import *# radiobutton --- 單選框----多個(gè)值中只能選一個(gè)root = Tk()root.title('RadioButton組件')root.geometry('400x100')def sel_gender(): if gender_check.get() == 1: Label_select_gender['text'] = '男' else: Label_select_gender['text'] = '女'def sel_education(): Label_select_education['text'] = education_list[int(education_check.get())]# 性別單選Label_gender = Label(root,text = '性別:')Label_gender.grid(row = 0,column = 0,padx = 5,pady = 5)gender_check = IntVar()# 用哪個(gè)變量接收它是否被選中,variable,綁定的值是同一個(gè)表示一組,variable通過get方法能獲得value的值# 最終選中后取什么值: value,同一組radiobutton中value的值最好是不同的# 性別的單選radio_boy = Radiobutton(root,text = '男',variable = gender_check,value = 1,command = sel_gender)radio_boy.grid(row = 0,column = 1,padx = 5,pady = 5)radio_boy = Radiobutton(root,text = '女',variable = gender_check,value = 0,command = sel_gender)radio_boy.grid(row = 0,column = 2,padx = 5,pady = 5)# 學(xué)歷education_list = ['高中','???,'本科','碩士','博士']Label_education = Label(root,text = '學(xué)歷:')Label_education.grid(row = 1,column = 0,padx = 5,pady = 5)education_check = IntVar()for i in range(0,len(education_list)): radio = Radiobutton(root,text = education_list[i],variable = education_check,value = i,command = sel_education) radio.grid(row = 1,column = i + 1,padx = 5,pady = 5)Label01 = Label(root,text = '所選的值為:')Label01.grid(row = 2 , column = 0)Label_select_gender = Label(root,text = '')Label_select_gender.grid(row = 2 , column = 1)Label_select_education = Label(root,text = '')Label_select_education.grid(row = 2 , column = 2)# 展示控件root.mainloop() 演示效果: 4. 下拉框ComboBox
效果演示: 5. 容器LabelFrame把具有相同功能的模塊組合在一起,并且加上一個(gè)名字,這個(gè)控件能讓你的界面更加有條理 # LabelFramefrom tkinter import *from tkinter.ttk import *root = Tk()root.title('LabelFrame控件')LabelFrame_query = LabelFrame(root,text = '學(xué)生信息查詢')LabelFrame_query.pack(padx = 10,pady = 10)# 如果不加控件的話,LabelFrame是看不見的Label01 = Label(LabelFrame_query,text = '學(xué)號(hào)')Label01.pack(side = LEFT,padx = 5,pady = 5)Entry01 = Entry(LabelFrame_query,width = 10)Entry01.pack(side = LEFT,padx = 5,pady = 5)Label02 = Label(LabelFrame_query,text = '姓名')Label02.pack(side = LEFT,padx = 5,pady = 5)Entry02 = Entry(LabelFrame_query,width = 10)Entry02.pack(side = LEFT,padx = 5,pady = 5)Label03 = Label(LabelFrame_query,text = '班級(jí)')Label03.pack(side = LEFT,padx = 5,pady = 5)Entry03 = Entry(LabelFrame_query,width = 10)Entry03.pack(side = LEFT,padx = 5,pady = 5)Button01 = Button(LabelFrame_query,text = '查詢',width = 5)Button01.pack(side = LEFT,padx = 15,pady = 5)root.mainloop() 運(yùn)行效果: 6. 樹狀視圖TreeView
運(yùn)行效果: 7. Style屬性增強(qiáng)的ttk包里沒法用tkinter的傳統(tǒng)屬性進(jìn)行設(shè)置比如bg和fg,我們需要通過style對(duì)象來對(duì)其設(shè)置;注意:我們對(duì)實(shí)例化對(duì)象style01進(jìn)行配置, style01.configure('TLabel',font = ('華文黑體',18),background = 'green',foreground = 'blue') 第一個(gè)參數(shù)不是對(duì)象的名稱,而是對(duì)象的某一類,其名稱是有規(guī)定的,不是隨便取的,由于這里是對(duì)Label 的style進(jìn)行命令,所以我們只能命名成TLabel,具體的組件與名稱的對(duì)應(yīng)關(guān)系如下: Style對(duì)象名稱
效果演示: 拓展:如果只想對(duì)某類中的某些控件生效,那么就必須要使用custom.Stylename格式來進(jìn)行命名;如我創(chuàng)建的style01的Stylename名稱是username.TLabel,這里的username是自定義字段,那么后面的Label控件如果沒有指定style是username.TLabel就不會(huì)具有style01的屬性 from tkinter import *from tkinter.ttk import *root = Tk()root.title('style屬性')root.geometry('300x200')# 實(shí)例化一個(gè)style對(duì)象style01style01 = Style()# 對(duì)style01進(jìn)行配置,Stylename屬性設(shè)置為password.TLablestyle01.configure('password.TLabel',font = ('華文黑體',18),background = 'green',foreground = 'blue')# 把Label01控件綁定給style01對(duì)象Label01 = Label(root,text = '用戶名',style = 'password.TLabel')Label01.pack(padx = 10,pady = 10)Label02 = Label(root,text = '密碼')Label02.pack(padx = 10,pady = 10)# 展示窗體root.mainloop() 這樣控件的顯示效果如下:
|
|