天天看點

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

wxPython是一套基于Python的第三方GUI插件,可用Python制作豐富的圖形化界面程式。

安裝:pip install wxPython 或者 網站下載下傳安裝https://pypi.org/project/wxPython/#files

demo和docs下載下傳:https://extras.wxpython.org/wxPython4/extras/

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

wxPython demo:

運作demo:直接cd到包路徑,然後使用“python demo.py”或者“pythonw demo.pyw”。

wxPython中大部分控件的使用效果都可以在demo程式中看到,是以如果想要找某個效果的控件,就可以去demo程式中去找,第一次接觸wxPython建議将demo程式的全部展示看一遍,以便以後用的時候友善找。另外,想要看demo的源代碼,除了在demo程式中看,也可以使用PyCharm等工具直接打開對應檔案包即可檢視整個demo程式的源代碼。

wxPython docs:

運作docs:直接使用浏覽器打開檔案夾中的index.html,然後就可以查找想要的文檔資訊了。

wxPython中控件的初始化方法、事件和各種方法在接口文檔中都有詳細的說明,或者你不知道某個控件有哪些方法時,也不妨去看看接口文檔。

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

電子書推薦:

demo和docs中的說明雖然已經很豐富了,但是某些控件的demo代碼并不是太直覺,docs中的說明也是全英文的,是以在實際開發的時候還是會有很多不明白的問題,這些問題除了網上搜答案之外,推薦一本電子書《wxPython實戰(中文版)高清.pdf》,這本電子書雖然在wxPython版本上有差異,但是對于控件的使用說明可以說非常詳細了,同時還有獨立的demo代碼,對學習和使用wxPython非常有幫助。

wxPython使用

wxPython中的一些基礎控件使用在demo和docs中都可以很容易找到,這裡就寫一些自己的使用總結和經驗分享,涉及到的控件的構造函數、方法和事件等可自行查閱API文檔或者相關書籍(如《wxPython實戰(中文版)高清.pdf》)。

簡單demo

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

importwx#一般GUI程式的最外層架構使用wx.Frame

classMyFrame(wx.Frame):def __init__(self):

super().__init__(None, -1, title='StaticBoxSizer Test')#建立一個panel,作為主面闆

self.panel = wx.Panel(self, size=(250, 50))#建立兩個按鈕,用于彈出消息和關閉程式

self.btn_hello = wx.Button(self.panel, label='Hello World')

self.btn_exit= wx.Button(self.panel, label='Exit')#給按鈕事件綁定按鈕事件方法,不同的控件都有對應的事件,可查閱API文檔DOCS

self.btn_hello.Bind(wx.EVT_BUTTON, self.on_helloworld)

self.btn_exit.Bind(wx.EVT_BUTTON, self.on_exit)#建立一個sizer用于界面布局,界面布局最好不使用pos參數寫死,不然以後不好維護

self.box_sizer =wx.BoxSizer()

self.box_sizer.Add(self.btn_hello, 0, wx.ALL,10)

self.box_sizer.Add(self.btn_exit, 0, wx.ALL,10)

self.panel.SetSizer(self.box_sizer)#界面設計好後,如果使用到了sizer布局控件,一般需要使用Layout重新繪制界面

self.box_sizer.Layout()

self.panel.Layout()

self.Layout()#Fit方法使架構自适應内部控件

self.Fit()#事件方法,的第二個參數evt或者event一定不要忘了,不然這個方法會報錯

#類中可能有很多個方法,事件方法建議約定一個容易識别的命名方式,比如我這裡是以“on_”開頭

defon_helloworld(self, event):"""彈出消息:Welcome to WxPython!"""

#建立一個消息彈窗,用于顯示消息

wx.MessageBox('Welcome to WxPython!')defon_exit(self, evt):"""退出程式"""wx.Exit()if __name__ == '__main__':

app=wx.App()

myframe=MyFrame()

myframe.Show()

app.MainLoop()

進度條對話框

彈窗式進度條:wx.ProgressDialog

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

wx.ProgressDialog為進度條顯示彈窗,它的唯一的方法Update(value,newmsg=””),value參數是進度條的新的内部的值,調用update将導緻進度條根據新的計數值與最大計算值的比例重繪。如果使用可選的參數newmsg,那麼進度條上的文本消息将變為該字元串,這讓你可以給使用者一個關于目前進度的文本描述。Update方法傳回兩個參數“continue”和“skip”,分别預設傳回“True”和“False”,在Update時,若使用者點選過“Cancel”按鈕(如果有)或者關閉了對話框,“continue”就傳回的是“False”(可用于中斷進度條),而“skip”隻有點選了“Cancel”按鈕後才會傳回“True”。

GUI程式布局

雖然控件本身也可以使用pos參數來指定控件的位置,但是推薦使用wxpython的布局控件來進行布局,布局控件不僅能更好的展示布局效果,而且也友善日後的維護工作。

由于在demo和docs中不好直接看到布局控件的效果,以下介紹一些常用布局控件用法和效果:

簡單網格布局控件:wx.GridSizer

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

importwxclassMyFrame(wx.Frame):def __init__(self):

super().__init__(None, -1, title='GridSizer Test', size=(300, 400))#建立一個wx.GridSizer, 3行3列,行間隔5, 列間隔5

grid_sizer = wx.GridSizer(3, 3, 5, 5)for i in range(9):

panel = wx.Panel(self)

panel.SetMinSize((100, 100))#從左到右,從上到下,一次将控件wx.Panel添加到wx.GridSizer中

grid_sizer.Add(panel)#将wx.GridSizer與架構控件wx.Frame關聯起來

self.SetSizer(grid_sizer)#使架構自适應内部控件

self.Fit()if __name__ == '__main__':

app=wx.App()

myframe=MyFrame()

myframe.Show()

app.MainLoop()

wx.GridSizer為簡單網格布局控件,初始化時需要指定行數和列數,以及行和列之間的間隔。特點是每個“格子”的尺寸大小都是一樣的,比較整齊,這裡的格子指的是布局控件給定的空間,而不是放在格子中的控件的大小。

當視窗大小發生變化時,預設所有的格子都會随着發生變化。

如果格子中的控件的大小不一緻時,則會以所有控件中最大的“長”和“寬”作為每個格子的尺寸大小。

使用Add方法在網格中添加控件時,隻能按順序添加控件。

更加靈活的網格布局控件:wx.FlexGridSizer

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

import wx

classMyFrame(wx.Frame):def __init__(self):

super().__init__(None, -1, title='FlexGridSizer Test', size=(300, 400))#建立一個wx.FlexGridSizer, 3行3列,行間隔5, 列間隔5

grid_sizer = wx.FlexGridSizer(3, 3, 5, 5)for i in range(9):

panel=wx.Panel(self)if i == 4:

panel.SetMinSize((200, 100))else:

panel.SetMinSize((100, 100))#從左到右,從上到下,一次将控件wx.Panel添加到wx.FlexGridSizer

grid_sizer.Add(panel)#指定第1列是可擴充的

grid_sizer.AddGrowableRow(1)#将wx.FlexGridSizer.Frame關聯起來

self.SetSizer(grid_sizer)#使架構自适應内部控件

self.Fit()

if __name__ == '__main__':

app =wx.App()

myframe =MyFrame()

myframe.Show()

app.MainLoop()

wx.FlexGridSizer布局控件,相比于wx.GridSizer,更加靈活的地方在于,可以在某行或者某列上進行設定,即每一行或者每一列它的尺寸大小是獨立的。

每一行(列)會以這一行(列)的最大的“長”(“寬”)作為這一行(列)的尺寸大小。

當視窗大小發生變化時,預設整個wx.FlexGridSizer是固定不變的,除非使用wx.FlexGridSizer的方法AddGrowableRow(AddGrowableCol)指定某行(列)是可以跟着視窗大小的擴充而擴充。

使用Add方法在網格中添加控件時,隻能按順序添加控件。

進階的網格布局控件:wx.GridBagSizer

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

import wx

classMyFrame(wx.Frame):

def __init__(self):

super().__init__(None, -1, title='GridBagSizer Test', size=(300, 400))#建立一個wx.GridBagSizer, 行間隔5, 列間隔5

grid_sizer = wx.GridBagSizer(5, 5)for row in range(3):for col in range(3):

panel=wx.Panel(self)

panel.SetMinSize((100, 100))#wx.GridBagSizer的Add方法需要指定添加的位置

grid_sizer.Add(panel, pos=(row, col))#在第0行第3列,添加一個控件,占3行和1列的空間,wx.EXPAND表示控件擴充至填滿整個“格子”的空間

panel_right =wx.Panel(self)

panel_right.SetMinSize((100, 100))

grid_sizer.Add(panel_right, pos=(0, 3), span=(3, 1), flag=wx.EXPAND)#在第3行第0列,添加一個控件,占1行和4列的空間,wx.EXPAND表示控件擴充至填滿整個“格子”的空間

panel_bottom =wx.Panel(self)

panel_bottom.SetMinSize((100, 100))

grid_sizer.Add(panel_bottom, pos=(3, 0), span=(1, 4), flag=wx.EXPAND)#将wx.GridBagSizer.Frame關聯起來

self.SetSizer(grid_sizer)#使架構自适應内部控件

self.Fit()

if __name__ == '__main__':

app =wx.App()

myframe =MyFrame()

myframe.Show()

app.MainLoop()

wx.GridBagSizer布局控件,相比于wx.FlexGridSizer和wx.GridSizer,多了兩個特性,一是可以初始化時不用指定“格子”數量,在往“格子”中添加控件時可以不按順序添加,直接指定控件添加的位置即可,二是一個“格子”可以跨越多個單元格顯示。

當視窗大小變化時,與wx.FlexGridSizer一樣,預設是不變的,需要自己指定哪行(列)是可擴充的。

此控件在使用Add方法時,必須指明添加的位置,即pos參數。

橫向(縱向)布局控件:wx.BoxSizer

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)
python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

import wx

classMyFrame(wx.Frame):def __init__(self):

super().__init__(None, -1, title='BoxSizer Test', size=(300, 400))#建立一個wx.BoxSizer, 預設是wx.HORIZONTAL,即橫向的

box_sizer =wx.BoxSizer()#也可指定為wx.VERTICAL,即縱向的

#grid_sizer = wx.BoxSizer(wx.VERTICAL)

for row in range(3):

panel=wx.Panel(self)

panel.SetMinSize((100, 100))#從左到右(從上到下)依次添加控件

#第二個參數為0時,視窗擴充時,格子尺寸不會變化,不為0時會跟着擴充變化

#wx.ALL表示所有邊框(此處邊框為5)

#wx.EXPAND表示控件填滿整個“格子”

box_sizer.Add(panel, 1, wx.ALL | wx.EXPAND, 5)#将wx.BoxSizer.Frame關聯起來

self.SetSizer(box_sizer)#使架構自适應内部控件

self.Fit()

if __name__ == '__main__':

app =wx.App()

myframe =MyFrame()

myframe.Show()

app.MainLoop()

wx.BoxSizer布局控件隻能橫向或者二縱向添加控件,預設是橫向的,可以使用wx.BoxSizer(wx.VERTICAL)使之變為縱向的,并且沒有特定的“格子”數,可以一直添加控件。

在視窗大小發生變化時,wx.BoxSizer隻能橫向或者縱向擴充。

在使用Add方法添加控件時,如果第二個參數proportion指定為0(預設),則“格子”在視窗大小變化時會保持不變,如果需要格子跟着擴充,一般可以指定為1。

帶有标簽和邊框線的橫向(縱向布局控件):wx.StaticBoxSizer

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)
python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

import wx

classMyFrame(wx.Frame):def __init__(self):

super().__init__(None, -1, title='StaticBoxSizer Test', size=(500, 700))#建立一個wx.StaticBox(帶有标簽和邊框線)

staticbox = wx.StaticBox(self, label="StaticBoxSizer Test")#wx.StaticBoxSizer初始化時需要傳入一個wx.StaticBox,方向預設是橫向

staticbox_sizer =wx.StaticBoxSizer(staticbox)#也可指定為wx.VERTICAL,即縱向的

#staticbox_sizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)

for row in range(3):

panel=wx.Panel(self)

panel.SetMinSize((100, 100))#從左到右(從上到下)依次添加控件

#第二個參數為0時,視窗擴充時,格子尺寸不會變化,不為0時會跟着擴充變化

#wx.ALL表示所有邊框(此處邊框為5)

#wx.EXPAND表示控件填滿整個“格子”

staticbox_sizer.Add(panel, 1, wx.ALL | wx.EXPAND, 5)#這裡單獨在建立一個wx.BoxSizer是為了在界面中顯示出wx.StaticBoxSizer的邊框線

box_sizer =wx.BoxSizer()

box_sizer.Add(staticbox_sizer,1, wx.ALL | wx.EXPAND, 5)#将wx.BoxSizer.Frame關聯起來

self.SetSizer(box_sizer)#使架構自适應内部控件

self.Fit()if __name__ == '__main__':

app=wx.App()

myframe=MyFrame()

myframe.Show()

app.MainLoop()

wx.StaticBoxSizer布局控件其實就是相當于在wx.BoxSizer外面套了一個wx.StaticBox,用法與wx.BoxSizer是相同的。

在wxPython中使用Matplotlib進行繪圖

Matplotlib是一個用于繪圖的Python三方庫,可以繪制折線圖、函數圖、柱狀圖、餅圖等多種圖形。但是在wxPython中不能直接使用Matplotlib來進行繪圖,需要使用Matplotlib提供給wxPython的接口matplotlib.backends.backend_wxagg來進行嵌入和繪制。

關于Matplotlib,可以參考我另一篇筆記:https://www.cnblogs.com/guyuyun/p/10486587.html

簡單示例:

python圖形化界面庫_Python三方庫:wxPython(GUI圖形使用者界面)

#-*- coding:utf-8 -*-

importwxfrom matplotlib importpyplotfrom matplotlib.backends.backend_wxagg importFigureCanvasWxAggclassTestMpltFrame(wx.Frame):def __init__(self):

super().__init__(None, size=(650, 500), title='Test Matplotlib Frame')

self.panel=wx.Panel(self)#subplots預設傳回一個Figure和一行一列的子圖對象

self.fig, self.axe =pyplot.subplots()#使用FigureCanvasWxAgg來建立Figure的背景畫布

self.canvas = FigureCanvasWxAgg(self, -1, self.fig)#繪制一條普通的折線圖

self.x_data = [1, 2, 4]

self.y_data= [2, 5, 1]

self.axe.plot(self.x_data, self.y_data)if __name__ == '__main__':

app=wx.App()

test_mplt_frame=TestMpltFrame()

test_mplt_frame.Show()

app.MainLoop()