1. 程式人生 > >wxPython開發總結---Frame,Panel以及一種專案架構

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的資料和顯示狀態。

原始碼和更多說明請檢視: