Python GUI介面程式設計
阿新 • • 發佈:2018-12-13
wxPython
安裝wxPython
pip install -U wxPython
C:\Users> pip install -U wxPython Collecting wxPython Downloading https://files.pythonhosted.org/packages/34/41/e0e109a72966f596a5b93123d94eaabd53509ef6766fa3321b4bfadbbb14/wxPython-4.0.3-cp37-cp37m-win_amd64.whl (22.7MB) 100% |████████████████████████████████| 22.7MB 819kB/s Collecting PyPubSub (from wxPython) Downloading https://files.pythonhosted.org/packages/ab/9e/3b50915d3346971aaa49074425788598ee4907e67c097e013f1a862bd45c/Pypubsub-4.0.0-py3-none-any.whl (63kB) 100% |████████████████████████████████| 71kB 1.5MB/s Requirement already satisfied, skipping upgrade: six in d:\python\lib\site-packages (from wxPython) (1.11.0) Installing collected packages: PyPubSub, wxPython Successfully installed PyPubSub-4.0.0 wxPython-4.0.3
wxPython的兩個基礎物件,應用程式物件和頂級視窗:
- 應用程式物件管理主事件迴圈,主事件迴圈是wxPython程式的動力。如果沒有應用程式物件,wxPython應用程式將不能執行。
- 頂級視窗通常用於管理最重要的資料,控制並呈現給使用者。
建立一個wx.App的子類
- 定義子類wx.App
- 在定義子類中寫一個OnInit()初始化方法
- 在程式的主要部分建立這個類的一個例項
- 呼叫應用程式例項的MainLoop方法。這個方法將程式的控制權轉交給wxPython
import wx # 匯入wxPython class App(wx.App): def OnInit(self): # 初始化方法 frame = wx.Frame(parent=None, title='第一個視窗程式') # 建立頂級視窗 frame.Show() # 顯示視窗 return True # 返回值(返回視窗,在螢幕展示) if __name__ == '__main__': app = App() # 例項化App類 app.MainLoop() # 呼叫App類的MainLoop()主迴圈方法
執行結果:
直接使用wx.App
通常,如果在系統中只有一個視窗的話,可以不建立wx.App子類,直接使用wx.App。這個類提供了一個最基本的OnInit()初始化方法。
import wx # 匯入wxPython
app = wx.App() # 初始化wx.App類
frame = wx.Frame(None, title='第一個視窗程式') # 定義一個頂級視窗
frame.Show() # 顯示視窗
app.MainLoop() # 呼叫wx.App類的MainLoop()主迴圈方法
執行結果:
使用wx.Frame框架
wx.Frame(parent=None, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE, name="frame")
- parent:框架的父視窗。如果是頂級視窗,這個值是None
- id:關於新視窗的wxPython ID號。通常設為-1,讓wxPython自動生成一個新的ID
- title:視窗標題
- pos:一個wx.Point物件,它指定這個新視窗的左上角在螢幕中的位置。在圖形使用者介面程式中,通常是(0,0)是顯示器的左上角。這個預設值(-1,-1)將讓系統決定視窗的位置
- size:一個wx.Python物件,他指定這個視窗的初始尺寸,這個預設值(-1,-1)將讓系統決定視窗的初始尺寸
- style:指定視窗的型別的常量。可以使用或運算來組合他們。
- name:框架內在的名字。可以使用它來尋找這個視窗
示例程式碼:
import wx # 匯入wxPython
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, title="建立Frame", pos=(100, 100), size=(300, 300))
if __name__ == '__main__':
app = wx.App() # 初始化應用
frame = MyFrame(parent=None, id=1) # 例項MyFrame類,並傳遞引數
frame.Show() # 顯示視窗
app.MainLoop() # 呼叫MainLoop()主迴圈方法
執行結果:
常用控制元件
StaticText文字類
建立完視窗以後,我們可以在視窗內新增一些控制元件,所謂的控制元件,就是經常使用的按鈕、文字、輸入框、單選框等。
wx.StaticText(parent, id, lable, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name="staticText")
- parent:父視窗部件
- id:識別符號。使用-1可以自動建立一個唯一的標識
- lable:顯示在靜態控制元件中的文字內容
- pos:一個wx.Point或者一個Python元組,它是視窗部件的位置
- size:一個wx.Size或一個Python元組,它是視窗部件的尺寸
- style:樣式標記
- name:物件名字
例項程式碼: 使用wx.StaticText輸出Python之禪
# -*- coding:utf-8 -*-
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, title="建立StaticText類",
pos=(100, 100), size=(600, 400))
panel = wx.Panel(self) # 建立畫板
# 建立標題,並設定字型
title = wx.StaticText(panel, label='Python之禪——Tim Peters', pos=(100, 20))
font = wx.Font(16, wx.DEFAULT, wx.FONTSTYLE_NORMAL, wx.NORMAL)
title.SetFont(font)
# 建立文字
wx.StaticText(panel, label='優美勝於醜陋',pos=(50, 50))
wx.StaticText(panel, label='明瞭勝於晦澀',pos=(50, 70))
wx.StaticText(panel, label='簡潔勝於複雜',pos=(50, 90))
wx.StaticText(panel, label='複雜勝於凌亂',pos=(50, 110))
wx.StaticText(panel, label='扁平勝於巢狀',pos=(50, 130))
wx.StaticText(panel, label='間隔勝於緊湊',pos=(50, 150))
wx.StaticText(panel, label='可讀性很重要',pos=(50, 170))
wx.StaticText(panel, label='即便假借特例的實用性之名,也不可違背這些規則', pos=(50,190))
wx.StaticText(panel, label='不要包容所有錯誤,除非你確定需要這樣做', pos=(50, 210))
wx.StaticText(panel, label='當存在多種可能,不要嘗試去猜測', pos=(50, 230))
wx.StaticText(panel, label='而是儘量找一種,最好是唯一一種明顯的解決方案', pos=(50, 250))
wx.StaticText(panel, label='雖然這並不容易,因為你不是 Python 之父', pos=(50, 270))
wx.StaticText(panel, label='做也許好過不做,但不假思索就動手還不如不做', pos=(50, 290))
wx.StaticText(panel, label='如果你無法向人描述你的方案,那肯定不是一個好方案;反之亦然', pos=(50, 310))
wx.StaticText(panel, label='名稱空間是一種絕妙的理念,我們應當多加利用', pos=(50, 330))
if __name__ == '__main__':
app = wx.App() # 初始化應用
frame = MyFrame(parent=None, id=-1) # 例項MyFrame類,並傳遞引數
frame.Show() # 顯示視窗
app.MainLoop() # 呼叫主迴圈方法
上述程式碼中,使用panel = wx.Panel(self)來建立畫板,並將panel 作為父類,然後將元件放入窗體中,此外,使用wx.Font類來設定字型。建立一個字型例項,需要使用如下建構函式:
wx.Font(pointSize, family, style, weight, underline=False, faceName="", encoding=wx.FONTENCODING_DEFAULT)
- pointSize:字型的整數尺寸,單位為磅
- family:用於快速的指定一個字型而不需要知道該字型實際的名字
- style:用於指定字型是否傾斜
- weight:指明字型醒目程度
- underline:僅在Windows系統下有效,如果取值為True,則加下劃線,如果為False則無下劃線
- faceName:指定字型名
- encoding:執行在幾個編碼中選擇一個,大多數情況可以使用預設編碼
執行結果:
TextCtrl輸入文字
wx.TextCtrl(parent, id, value="", pos=wx.DefaultPosition, size=wx.DefaultSize,style=0,validator=wx.DefaultValidator name=wx.TextCtrlNameStr)
- style:單行wx.TextCtrl的樣式,取值如下:
- wx.TE_CENTER:控制元件中的文字居中
- wx.TE_LEFT:控制元件中的文字左對齊
- wx.TE_NOHIDESEL:文字始終高亮顯示,僅適用於Windows
- wx.TE_PASSWORD:不顯示所鍵入的文字,以(*)代替顯示
- wx.TE_PROCESS_ENTER:如果使用改引數,那麼當用戶在控制元件內按下
Enter
鍵時,一個文字輸入事件將被觸發。否則,按鍵事件由該文字控制元件或該對話方塊管理 - wx.TE_PROCESS_TAB:如果指定了這個樣式,那麼通常的字元事件在按下
Tab
鍵時建立(一般意味著一個製表符將被插入文字)。否則,tab由對話方塊來管理,通常是控制元件間切換 - wx.TE_READONLY:文字控制元件為只讀,使用者不能修改其中文字
- wx.TE_RIGHT:控制元件中的文字右對齊
- value:顯示在該控制元件中的初始文字
- validator:常用於過濾資料以確保只能鍵入要接受的資料
示例程式碼:
# -*- coding:utf-8 -*-
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, title="建立TextCtrl類", size=(400, 300))
#建立面板
panel = wx.Panel(self)
# 建立文字和輸入框
self.title = wx.StaticText(panel, label="請輸入使用者名稱和密碼", pos=(140, 20))
self.label_user = wx.StaticText(panel, label="使用者名稱:", pos=(50, 50))
self.text_user = wx.TextCtrl(panel, pos=(100, 50), size=(235, 25), style=wx.TE_LEFT)
self.label_pwd = wx.StaticText(panel, pos=(50, 90), label="密 碼:")
self.text_password = wx.TextCtrl(panel, pos=(100, 90), size=(235, 25), style=wx.TE_PASSWORD)
if __name__ == '__main__':
app = wx.App() # 初始化應用
frame = MyFrame(parent=None, id=-1) # 例項MyFrame類,並傳遞引數
frame.Show() # 顯示視窗
app.MainLoop() # 呼叫主迴圈方法
執行結果:
Button按鈕類
wx.Button(parent, id, lable, pos, size=wx.DefaultSize, style=0, validator, name="button")
wx.Button和wx.TextCtrl的引數基本相同,其中引數lable是顯示在按鈕上的文字
示例程式碼:
# -*- coding:utf-8 -*-
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, title="建立TextCtrl類", size=(400, 300))
panel = wx.Panel(self) # 建立面板
# 建立文字和輸入框
self.title = wx.StaticText(panel, label="請輸入使用者名稱和密碼", pos=(140, 20))
self.label_user = wx.StaticText(panel, label="使用者名稱:", pos=(50, 50))
self.text_user = wx.TextCtrl(panel, pos=(100, 50), size=(235, 25), style=wx.TE_LEFT)
self.label_pwd = wx.StaticText(panel, pos=(50, 90), label="密 碼:")
self.text_password = wx.TextCtrl(panel, pos=(100, 90), size=(235, 25), style=wx.TE_PASSWORD)
self.bt_confirm = wx.Button(panel, label='確定', pos=(105, 130)) # 建立“確定”按鈕
self.bt_cancel = wx.Button(panel, label='取消', pos=(195, 130)) # 建立“取消”按鈕
if __name__ == '__main__':
app = wx.App() # 初始化
frame = MyFrame(parent=None, id=-1) # 例項MyFrame類,並傳遞引數
frame.Show() # 顯示視窗
app.MainLoop() # 呼叫主迴圈方法
執行結果:
繫結事件
當我們點選按鈕後需要讓系統做出相應的響應,如執行某個判斷並給出提示,使用Bind()方法可以將事件處理函式繫結到給定的事件上:
bt_confirm.Bind(wx.EVT_BUTTON, OnclickSubmit)
示例程式碼:
點選確定,判斷密碼是否正確等
# -*- coding:utf-8 -*-
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, '使用者登入', size=(400, 300))
# 建立面板
panel = wx.Panel(self)
# 建立“確定”和“取消”按鈕, 並繫結事件
self.bt_confirm = wx.Button(panel, label='確定')
self.bt_confirm.Bind(wx.EVT_BUTTON, self.OnclickSubmit)
self.bt_cancel = wx.Button(panel, label='取消')
self.bt_cancel.Bind(wx.EVT_BUTTON, self.OnclickCancel)
# 建立文字,左對齊
self.title = wx.StaticText(panel, label="請輸入使用者名稱和密碼")
self.label_user = wx.StaticText(panel, label="使用者名稱:")
self.text_user = wx.TextCtrl(panel, style=wx.TE_LEFT)
self.label_pwd = wx.StaticText(panel, label="密 碼:")
self.text_password = wx.TextCtrl(panel, style=wx.TE_PASSWORD)
# 新增容器,容器中控制元件按橫向並排排列
hsizer_user = wx.BoxSizer(wx.HORIZONTAL)
hsizer_user.Add(self.label_user, proportion=0, flag=wx.ALL, border=5)
hsizer_user.Add(self.text_user, proportion=1, flag=wx.ALL, border=5)
hsizer_pwd = wx.BoxSizer(wx.HORIZONTAL)
hsizer_pwd.Add(self.label_pwd, proportion=0, flag=wx.ALL, border=5)
hsizer_pwd.Add(self.text_password, proportion=1, flag=wx.ALL, border=5)
hsizer_button = wx.BoxSizer(wx.HORIZONTAL)
hsizer_button.Add(self.bt_confirm, proportion=0, flag=wx.ALIGN_CENTER, border=5)
hsizer_button.Add(self.bt_cancel, proportion=0, flag=wx.ALIGN_CENTER, border=5)
# 新增容器,容器中控制元件按縱向並排排列
vsizer_all = wx.BoxSizer(wx.VERTICAL)
vsizer_all.Add(self.title, proportion=0, flag=wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER,
border=15)
vsizer_all.Add(hsizer_user, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
vsizer_all.Add(hsizer_pwd, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
vsizer_all.Add(hsizer_button, proportion=0, flag=wx.ALIGN_CENTER | wx.TOP, border=15)
panel.SetSizer(vsizer_all)
def OnclickSubmit(self, event):
""" 點選確定按鈕,執行方法 """
message = ""
username = self.text_user.GetValue() # 獲取輸入的使用者名稱
password = self.text_password.GetValue() # 獲取輸入的密碼
if username == "" or password == "": # 判斷使用者名稱或密碼是否為空
message = '使用者名稱或密碼不能為空'
elif username == 'admin' and password == '123456': # 使用者名稱和密碼正確
message = '登入成功'
else:
message = '使用者名稱和密碼不匹配' # 使用者名稱或密碼錯誤
wx.MessageBox(message) # 彈出提示框
def OnclickCancel(self, event): # 沒有event點選取消會報錯
""" 點選取消按鈕,執行方法 """
self.text_user.SetValue("") # 清空輸入的使用者名稱
self.text_password.SetValue("") # 清空輸入的密碼
if __name__ == '__main__':
app = wx.App() # 初始化
frame = MyFrame(parent=None, id=-1) # 例項MyFrame類,並傳遞引數
frame.Show() # 顯示視窗
app.MainLoop() # 呼叫主迴圈方法
執行結果: