1. 程式人生 > >python GUI程式設計

python GUI程式設計

GUI:Graphical User Interface圖形使用者介面

1  簡介

Tkinter是Python的預設GUI庫, 基於Tk工具包,該工具包最初是為工具命令語言(Tool Command Language,Tcl)設計的。Tk普及後,被移植到很多其他的指令碼語言中,包括Perl(Perl/Tk)、Ruby(Ruby/Tk)和Python(Tkinter)。

Python3模組為tkinter。

2  Tkinter和python程式設計

2.1  新增Tk到應用中

讓GUI 程式啟動和執行起來需要以下5 個主要步驟:

1.匯入tkinter模組。

2.建立一個頂層視窗物件,用於容納整個GUI應用。

3.在頂層視窗物件之上(或者“其中”)構建所有的GUI 元件(及其功能)。

4.通過底層的應用程式碼將這些GUI元件連線起來。

5.進入主事件迴圈

2.2  GUI程式設計介紹

1、視窗與控制元件

在GUI程式設計中,頂層的根視窗物件包含組成GUI應用的所有小視窗物件。它們可能是文字標籤、按鈕、列表框等。這些獨立的GUI元件稱為控制元件。所以當我們說建立一個頂層視窗時,只是表示需要一個地方來擺放所有的控制元件。

tkinter.Tk()返回的物件通常稱為根視窗

2、事件驅動處理

一個GUI應用從開始到結束就是通過整套事件體系來驅動的,事件可以包括按鈕按下(及釋放)、滑鼠移動、敲擊回車鍵等。

當佈局管理器排列好所有控制元件後,GUI應用進入其類似伺服器的無限迴圈。這個迴圈會一直執行,直到出現GUI事件,進行處理,然後再等待更多的事件去處理

3、佈局管理

Tk有3 種佈局管理器:

1)  Placer:提供控制元件的大小和擺放位置,然後管理器就會將其擺放好

2)  Packer:主要使用,把控制元件填充到正確的位置,然後對於之後的每個控制元件,會去尋找剩餘的空間進行填充

3)  Grid:基於網格座標,使用Grid來指定GUI控制元件的放置

2.3  Tk控制元件

控制元件

描述

Button

與Label類似,但提供額外的功能,如滑鼠懸浮、按下、釋放以及鍵盤活動/事件

Canvas

提供繪製形狀的功能(線段、橢圓、多邊形、矩形),可以包含影象或點陣圖

Checkbutton

一組選框,可以勾選其中的任意個(與HTML的checkbox輸入類似)

Entry

單行文字框,用於收集鍵盤輸入(與HTML的文字輸入類似)

Frame

包含其他控制元件的純容器

Label

用於包含文字或影象

LabelFrame

標籤和框架的組合,擁有額外的標籤屬性

Listbox

給使用者顯示一個選項列表來進行選擇

Menu

按下Menubutton後彈出的選項列表,使用者可以從中選擇

Menubutton

用於包含選單(下拉、級聯等)

Message

訊息。與Label類似,不過可以顯示成多行

PanedWindow

一個可以控制其他控制元件在其中擺放的容器控制元件

Radiobutton

一組按鈕,其中只有一個可以“按下”(與HTML的radio輸入類似)

Scale

線性“滑塊”控制元件,根據已設定的起始值和終止值,給出當前設定的精確值

Scrollbar

為Text、Canvas、Listbox、Enter等支援的控制元件提供滾動功能

Spinbox

Entry 和Button 的組合,允許對值進行調整

Text

多行文字框,用於收集(或顯示)使用者輸入的文字(與HTML的textarea類似)

Toplevel

與Frame類似,不過它提供了一個單獨的視窗容器

2.4  Tkinter示例

2.4.1  Label控制元件

1 import tkinter
2 
3 top = tkinter.Tk()       #建立了一個頂層視窗
4 
5 label = tkinter.Label(top,text='Hello World!')   #Label控制元件,包含Hello World字串
6 label.pack()            #使用Packer來管理和顯示控制元件
7 tkinter.mainloop()      #執行GUI應用,tkinter.mainloop()可以讓應用進入無限主迴圈中

執行結果:

2.4.2  Button控制元件

1 import tkinter
2 
3 top = tkinter.Tk()       #建立了一個頂層視窗
4 
5 #Button控制元件,當按鈕被按下(並且釋放)後,整個程式就會退出
6 label = tkinter.Button(top,text='quit',command=top.quit,bg='red',fg='green')  
7 label.pack()            #使用Packer來管理和顯示控制元件
8 tkinter.mainloop()      #執行GUI應用,tkinter.mainloop()可以讓應用進入無限主迴圈中

執行結果:

2.4.3  偏函式應用

1)偏函式

functools.partial偏函式的作用就是,把一個函式的某些引數給固定住(也就是設定預設值),返回一個新的函式,呼叫這個新函式會更簡單

2)偏函式應用示例

 1 from functools import partial as pto   #偏函式
 2 from tkinter import Tk,Button,X
 3 from tkinter.messagebox import showinfo,showwarning,showerror
 4 
 5 WARN = 'warn'
 6 CRIT = 'crit'
 7 REGU = 'regu'
 8 
 9 SIGNS = {
10     'do not enter':CRIT,
11     'railroad crossing':WARN,
12     '55\nspeed limit':REGU,
13     'wrong way':CRIT,
14     'merging traffic':WARN,
15     'one way':REGU
16 }
17 
18 ##各種標誌型別按鈕的回撥函式##
19 critCB = lambda:showerror('Error','Error Button Pressed!')
20 warnCB = lambda:showwarning('Warning','Warning Button Pressed!')
21 infoCB = lambda:showinfo('Info','Info Button Pressed!')
22 
23 top = Tk()     #頂層視窗
24 top.title('Road Signs')    #設定標題
25 Button(top,text='QUIT',command=top.quit,bg='red',fg='white').pack()   #設定QUIT按鈕,使用Packer來管理和顯示控制元件
26 
27 ##偏函式用法##
28 #模板化Button類和根視窗top;呼叫MyButton時,就會呼叫Button類(tkinter.Button()建立一個按鈕),並將top作為它的第一個引數
29 MyButton = pto(Button,top)  
30 #模板化每種標誌型別,建立單獨的按鈕型別
31 CritButton = pto(MyButton,command=critCB,bg='white',fg='red')
32 WarnButton = pto(MyButton,command=warnCB,bg='goldenrod1')
33 ReguButton = pto(MyButton,command=infoCB,bg='white')
34 
35 for eachSign in SIGNS:
36     signType = SIGNS[eachSign]
37     '''
38     expand置1 使能fill屬性
39     expand置0 關閉fill屬性
40     fill=X 當GUI窗體大小發生變化時,widget在X方向跟隨GUI窗體變化
41     fill=Y 當GUI窗體大小發生變化時,widget在Y方向跟隨GUI窗體變化
42     fill=BOTH 當GUI窗體大小發生變化時,widget在X、Y兩方向跟隨GUI窗體變化 
43     '''
44     # title() 方法返回"標題化"的字串,就是說所有單詞都是以大寫開始,其餘字母均為小寫
45     cmd = '%sButton(text=%r%s).pack(fill=X,expand=True)' % (signType.title(),eachSign,'.upper()' if signType == CRIT else '.title()')
46     #eval()將字串str當成有效的表示式來求值並返回計算結果
47     eval(cmd)
48 
49 top.mainloop()

執行結果:

2.4.4  Tkinter示例(目錄樹遍歷)

  1 import os
  2 from time import sleep
  3 from tkinter import *
  4 
  5 class DirList(object):
  6     def __init__(self,initdir=None):
  7         self.top = Tk()   #頂層視窗
  8         self.label = Label(self.top,text='Directory Lister V1.1') #Label控制元件,包含字串
  9         self.label.pack()  #使用Packer來管理和顯示控制元件
 10 
 11         self.cwd = StringVar(self.top)   #用於儲存當前所在的目錄名
 12 
 13         #用於顯示當前的目錄名
 14         self.dirl = Label(self.top,fg='blue',font=('Helvetica',12,'bold'))
 15         self.dirl.pack()
 16 
 17         #Scrollbar與Listbox控制元件包含在Frame控制元件中
 18         self.dirfm = Frame(self.top)
 19         self.dirsb = Scrollbar(self.dirfm)  #檔案樹超過Listbox的大小能夠移動列表
 20         #side按扭停靠在視窗的哪個位置,fill填充(x:水平方向,y:豎直方向,both:水平和豎直方向,none:不填充)
 21         self.dirsb.pack(side=RIGHT,fill=Y)  
 22         #列出目錄的檔案列表,yscrollcommand建立一個垂直滾動條 
 23         self.dirs = Listbox(self.dirfm,height=15,width=50,yscrollcommand=self.dirsb.set) 
 24         #繫結操作,這意味著將一個回撥函式與按鍵、滑鼠操作或者其他的一些事件連線起來,這裡當雙擊任意條目時,會呼叫setDirAndGo函式
 25         self.dirs.bind('<Double-1>',self.setDirAndGo)
 26         self.dirs.pack(side=LEFT,fill=BOTH)
 27         self.dirfm.pack()
 28 
 29         #建立一個文字框,可以輸入遍歷的目錄名
 30         #Entry是tkinter 用來接收字串等輸入的控制元件
 31         self.dirn = Entry(self.top,width=50,textvariable=self.cwd)
 32         #回車繫結
 33         self.dirn.bind('<Return>',self.doLS)
 34         self.dirn.pack()
 35 
 36         #定義一個按鈕框架
 37         self.bfm = Frame(self.top)
 38         self.clr = Button(self.bfm,text='Clear',command=self.clrDir,activeforeground='white',activebackground='blue')
 39         self.ls = Button(self.bfm,text='List Directory',command=self.doLS,activeforeground='white',activebackground='green')
 40         self.quit = Button(self.bfm,text='Quit',command=self.top.quit,activeforeground='white',activebackground='red')
 41         self.clr.pack(side=LEFT)
 42         self.ls.pack(side=LEFT)
 43         self.quit.pack(side=LEFT)
 44         self.bfm.pack()
 45 
 46         #初始化GUI程式,以當前工作目錄作為起始點
 47         if initdir:
 48             self.cwd.set(os.curdir) #os.curdir:返回當前目錄('.')
 49             self.doLS()
 50 
 51     '''
 52     清空TK字串變數cwd,當發生錯誤時可以回到之前的目錄
 53     ev預設為None,值是有視窗系統傳入的,回撥函式中可能會用到,也可能用不到
 54     '''
 55     def clrDir(self,ev=None):
 56         self.cwd.set('')
 57 
 58     #設定要遍歷的目錄函式
 59     def setDirAndGo(self,ev=None):
 60         self.last = self.cwd.get()
 61         self.dirs.config(selectbackground='red') #雙擊時,設定背景色為紅色
 62         check = self.dirs.get(self.dirs.curselection()) #curselection()返回當前選中項的索引,get()返回制定索引的項值
 63         if not check:
 64             check = os.curdir
 65         self.cwd.set(check)
 66         self.doLS()
 67 
 68     def doLS(self,ev=None):
 69         error=''
 70         tdir = self.cwd.get()
 71         if not tdir:tdir = os.curdir #os.curdir:返回當前目錄('.')
 72 
 73         if not os.path.exists(tdir): #判斷檔案是否存在
 74             error = tdir + ':no such file'
 75         elif not os.path.isdir(tdir): #判斷是否是目錄
 76             error = tdir + ':not a directory'
 77 
 78         if error:
 79             self.cwd.set(error)
 80             self.top.update()
 81             sleep(2)
 82             if not (hasattr(self,'last') and self.last):#hasattr判斷一個物件裡面是否有last屬性或者last方法
 83                 self.last = os.curdir
 84             self.cwd.set(self.last)
 85             self.dirs.config(selectbackground='LightSkyBlue')
 86             self.top.update()
 87             return
 88 
 89         self.cwd.set('FETCHING DIRECTORY CONTENTS...')
 90         self.top.update()
 91         dirlist = os.listdir(tdir) #獲取實際檔案列表
 92         dirlist.sort()
 93         os.chdir(tdir)  #改變當前工作目錄到指定的路徑
 94 
 95         self.dirl.config(text=os.getcwd())  #os.getcwd()返回當前程序的工作目錄
 96         self.dirs.delete(0,END)  #刪除所有元素
 97         #insert()匯入listbox中
 98         self.dirs.insert(END,os.curdir)  
 99         self.dirs.insert(END,os.pardir)  #os.pardir上級目錄
100         for eachFile in dirlist:
101             self.dirs.insert(END,eachFile)
102         self.cwd.set(os.curdir)
103         self.dirs.config(selectbackground='LightSkyBlue')
104 
105 def main():
106     DirList(os.curdir) #os.curdir:返回當前目錄('.')
107     mainloop()
108 
109 if __name__=='__main__':
110     main()

執行結果:

 

3  其他GUI

1)  Tix(Tk介面擴充套件)

2)  Pmw(Python MegaWidgets Tkinter擴充套件)

3)  wxPython(wxWidgets的Python版本)

4)  PyGTK(GTK+的python版本)