1. 程式人生 > >Python GUI介面程式設計

Python GUI介面程式設計

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的子類

  1. 定義子類wx.App
  2. 在定義子類中寫一個OnInit()初始化方法
  3. 在程式的主要部分建立這個類的一個例項
  4. 呼叫應用程式例項的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()                      # 呼叫主迴圈方法

執行結果: