wxPython開發總結---Frame,Panel以及一種專案架構
前一段時間用Python開發了一個教育類的PC桌面應用,邊學邊開發,現在陸續的將開發過程中學到的一些東西分享記錄下來,專案使用了wxPython框架。
wx庫不是Python自帶的庫檔案,需要首先在官網下載並安裝,windows可以在官網下載exe安裝檔案,Ubuntu和Mac可以使用pip install進行安裝,也可以使用原始碼安裝方式安裝。
安裝成功之後,使用import wx 來測試安裝成功與否,在進行wxPython程式設計中,也需要使用import wx 首先匯入wxPython的庫引用。
下面是第一個用wxPython構建的介面視窗:
【效果】
【程式碼實現】
#coding=utf-8""" 程式的主入口""" import wx class FirseFrame(wx.Frame): def __init__(self, parent=None, id=-1, title='', pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.DEFAULT_FRAME_STYLE): """ wx.Frame() 建構函式引數說明 : wx.Frame.__init__(self, Window parent, int id=-1, String title=EmptyString,Point pos=DefaultPosition, Size size=DefaultSize, long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> Frame """ wx.Frame.__init__(self, parent, id, title, pos, size, style) self.InitUI() pass def InitUI(self): self.SetBackgroundColour('#ffffff') """ wx.StaticText()建構函式引數說明 : __init__(self, Window parent, int id=-1, String label=EmptyString, Point pos=DefaultPosition, Size size=DefaultSize, long style=0, String name=StaticTextNameStr) -> StaticText """ content = wx.StaticText(self, -1, u'這是第一個視窗', pos=(20, 20)) content.SetForegroundColour('#000000') pass class MainApp(wx.App): def OnInit(self): self.frame = FirseFrame(id=-1, title=u'第一個視窗', pos=(10, 10), size=(230, 230)) self.frame.Show() return True def main(): app = MainApp() app.MainLoop() if __name__ == "__main__": main()
【說明】
if __name__ == "__main__": main()上面的程式碼是Python程式的主入口,在一個專案中有且只有一個,一個Python程式開始執行的時候,會找到這個入口,並從此開始執行。
class MainApp(wx.App): def OnInit(self): self.frame = FirseFrame(id=-1, title=u'第一個視窗', pos=(10, 10), size=(230, 230)) self.frame.Show() return True
wx.App是wxPython中一個App物件,在一個wxPython中有且只有一個,MainApp類繼承了wx.App類MainApp類被例項化之後,呼叫wx.App物件的MainLoop()方法便開始了一個wxPython程序。
關於編碼錯誤的問題,上面程式中,漢字字串前面加了一個u,表示該段字串的編碼/解碼方式是unicode的方式,如果專案執行Unicode編碼錯誤,可以在程式開始的地方加上下面一段程式碼:
import sys reload(sys) sys.setdefaultencoding('utf-8')
(1)wx.Frame
Frame可以看做是wxPython提供的控制元件繪製的視窗,我們可以將控制元件繪製在Frame上,便於管理。
在wxPython的原始碼中可以看到wxFrame的建構函式為:
""" wx.Frame() 建構函式引數說明 : __init__(self, Window parent, int id=-1, String title=EmptyString, Point pos=DefaultPosition, Size size=DefaultSize, long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> Frame """【說明】
pos是Frame在螢幕上顯示的位置, size為Frame視窗初始化繪製的大小
style是Frame顯示的屬性,常用的style樣式說明:
style=wx.CAPTION : 在Frame上增加一個標題欄 :
style=wx.CLOSE_BOX : 在Frame上顯示關閉框:
style=wx.MAXIMIZE_BOX : 在Frame上顯示最大化框
style=wx.MINIMIZE_BOX : 在Frame上顯示最小化框
style=wx.RESIZE_BORDER : 給Frame新增一個使用者可以自己改變Frame大小的邊框
style=wx.DEFAULT_FRAME_STYLE : 預設的Frame樣式:
可以看到預設樣式包含了所有的常見樣式(包括,標題,icon,最小化,最大化,可拖拽大小邊框,關閉),那麼要是我們想在預設樣式的基礎上出去某個樣式,可以:
style = wx.DEFAULT_FRAME_STYLE^(wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX|wx.CLOSE_BOX)
上面的樣式在預設樣式的基礎上,去除了 拖拽改變Frame大小屬性,去除了最大化,去除了最小化,去除了關閉。
效果如下:
當然要是隻去除一個樣式,e.g. 去除最大化:
style = wx.DEFAULT_FRAME_STYLE^wx.MAXIMIZE_BOX self.frame = FirseFrame(id=-1, title=u'第一個視窗', pos=(10, 10), size=(230, 230), style=style)效果:
pos是一個Frame顯示在螢幕上的位置座標,size是Frame初始化的大小,那麼要是我們希望我們的Frame在初始化之後顯示在螢幕的中間,可以首先獲得螢幕的大小,然後動態規定pos的值:
class MainApp(wx.App): def OnInit(self): style = wx.DEFAULT_FRAME_STYLE^wx.MAXIMIZE_BOX # wx.DisplaySize()獲得一個元組, e.g. (1440, 780) 表示當前裝置螢幕的長寬 windowSize = wx.DisplaySize() newPos = (windowSize[0] / 2, windowSize[1] / 2) self.frame = FirseFrame(id=-1, title=u'第一個視窗', pos=newPos, size=(230, 230), style=style) self.frame.Show() return True上面的程式碼通過wx.DisplaySize()獲得了裝置螢幕的大小,動態制定了Frame顯示的座標,使得Frame左上角位於螢幕的中心位置,這是一種方法,其實wxPython提供了一種自帶的介面:
只修改wxFrame類:
class FirseFrame(wx.Frame): def __init__(self, parent=None, id=-1, title='', pos=wx.DefaultSize, size=wx.DefaultSize, style= wx.DEFAULT_FRAME_STYLE): wx.Frame.__init__(self, parent, id, title, pos, size, style) self.InitUI() pass def InitUI(self): self.SetBackgroundColour('#ffffff') """ wx.StaticText()建構函式引數說明 : __init__(self, Window parent, int id=-1, String label=EmptyString, Point pos=DefaultPosition, Size size=DefaultSize, long style=0, String name=StaticTextNameStr) -> StaticText """ content = wx.StaticText(self, -1, u'這是第一個視窗', pos=(20, 20)) content.SetForegroundColour('#000000') self.Center() pass在FirseFrame(wx.Frame)的InitUI()函式的最後呼叫了 self.Center() 函式,告訴系統將該Frame顯示在螢幕的中間,系統會將Frame的中心放在裝置螢幕的中心位置,
同樣的,要是想讓Frame在初始化之後,最大化,一種方法就是將Frame的size設定為wx.DisplaySize(),和self.Center()相同,可以通過呼叫self.Maximize(True)來實現:
self.Maximize(True)
(2)wx.Panel
Panel可以看做是一個碎片化的Frame,當有一部分的控制元件需要同時處理,比如同時隱藏,同時顯示的時候,可以將這些控制元件的parent Window寫成同一個Panel,這樣方便於整體的操作。
""" __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, Size size=DefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER, String name=PanelNameStr) -> Panel """
(3)一種wxPython專案架構
當我們有多個Frame介面需要來回的跳轉,而Frame的顯示是在MainApp(wx.App)類中實現的,那麼就需要在MainApp(wx.App)這個類中實現一個Frame跳轉的介面,通過這個介面來完成多Frame的跳轉。
【說明】
FrameManager中,維護了一個字典,key=type,value=Frame,首次顯示Frame的時候,建立該Frame,並將其快取在字典中,再次顯示該Frame的時候,直接從字典中獲取得到gaiFrame,並通過Frame中自定義的方法UpdateDataAndUI(self, newData)介面,更新Frame的資料和顯示狀態。
原始碼和更多說明請檢視: