前言架構
wxPython是基於Python的跨平臺GUI擴展庫,對wxWidgets( C++ 編寫)封裝實現。GUI程序的開發中界面佈局是很重要的一個部分,合理的頁面佈局可以給予用戶良好使用體驗。雖然在GUI的控件和窗口布局上可使用座標,但更多且更方便的是用sizer來佈局。本文主要介紹wxPython的佈局管理應用以及在此基礎上實現的頁面切換功能。app
最小架構實現ide
wxPython程序由組件wx.App、wx.Frame、wx.Panel以及其餘widget控件/窗體(如wx.ComboBox, wx.Button)組成。一個wxPython程序只有一個wx.App建立的實例用於執行事件循環,至少一個Frame對象做爲控件的容器,調用Show()方法使其顯示,Frame中至少有一個Panel用來控制佈局的窗口,而其餘的控件創建在Panel之上。函數
在App類中未定義init()方法,但在Python中實例化一個對象時父方法wx.App.init()將被自動調用,若是定義了init()方法,須要手動調用基類的init()方法,如Frame類和Panel類中的實現(建立Frame類、Panel類可更靈活地設計咱們所須要的GUI)。OnInit()是wxPython所特有的一個方法,在應用程序建立後到事件循環開始前被wx.App父類調用,需返回一個True的布爾值。SetTopWindow()方法設置當前Frame爲應用程序的頂級窗口,該方法繼承自wx.App父類。oop
應用程序一旦進入主事件循環,控制權將轉交給wxPython,程序響應用戶的鼠標和鍵盤事件。當應用程序的全部Frame關閉後app.MainLoop()方法結束並退出程序。佈局
class Panel(wx.Panel): def __init__(self,parent): wx.Panel.__init__(self,parent=parent, id=-1) pass class Frame(wx.Frame): def __init__(self): wx.Frame.__init__(self, parent = None, title = u'量化軟件', size=(1000,600), style=wx.DEFAULT_FRAME_STYLE^wx.MAXIMIZE_BOX) self.MPL = Panel(self) pass class App(wx.App): def OnInit(self): self.frame = Frame() self.frame.Show() self.SetTopWindow(self.frame) return True if __name__ == '__main__': app = App() app.MainLoop()
佈局管理介紹優化
控件可經過絕對座標形式定位在容器中,由構造函數中pos參數指定以像素爲單位的座標值。如wx.TextCtrl的構造函數所示:spa
wx.TextCtrl(parent,id,value='',pos=wx.DefaultPostion,size=wx.DefaultSize,style=0,validator=wx.DefaultValidator,name=wx.TextCtrlNameStr)
絕對定位方式需爲每個控件設計大小和位置,修改佈局時十分繁瑣,並且調整容器(Frame或Panel)尺寸時控件沒法對應改變。wxPython的佈局管理器Sizer能對容器中的控件進行更優雅的管理,隨着容器尺寸的變化自動計算控件最優化的大小和位置。設計
wxPython中定義的sizer主要有wx.BoxSizer,wx.StaticBoxSizer,wx.GridSizer,wx.FlexGridSizer和wx.GridBagSizer,它們繼承了Wx.Sizer基類,並在此之上各自具備管理窗口布局的規則。code
如下經過例程介紹Sizer佈局應用。wx.BoxSizer的佈局方向分爲橫向和縱向兩種,而且能夠在橫向或縱向方向上包含子sizer以建立嵌套的佈局。按下表所示要求進行佈局,即ParaPanel、MPL、RightPanel三個面板採用橫向boxsizer佈局。ParaPanel嵌套wx.StaticBoxSizer佈局器及wx.RadioBox和wx.TextCtrl控件,三者採用縱向boxsizer排布。RightPanel中嵌套wx.FlexGridSizer佈局器指定3個wx.Button控件按網格尺寸排布。
(1) 分別建立ParaPanel、MPL、RightPanel面板,建立一個縱向wx.BoxSizer用於排列ParaPanel中控件,建立一個橫向wx.BoxSizer用於排布ParaPanel、MPL、RightPanel面板。
self.MPL = PanelA(self) self.ParaPanel = wx.Panel(self,-1) self.RightPanel = wx.Panel(self,-1) vboxnetA = wx.BoxSizer(wx.VERTICAL)#縱向box self.HBoxPanel = wx.BoxSizer(wx.HORIZONTAL)
(2)建立一個wx.StaticBox靜態框對象,建立wx.StaticBoxSizer佈局管理器將靜態框做爲參數傳入進行佈局管理,建立控件並經過Add()方法添加至StaticBoxSizer佈局管理器中。
paraInput_Box = wx.StaticBox(self.ParaPanel, -1, u'參數輸入')
paraInput_Sizer = wx.StaticBoxSizer(paraInput_Box, wx.VERTICAL)
stockCode_Text = wx.StaticText(self.ParaPanel, -1, u'模塊名稱')
stockData_Text = wx.StaticText(self.ParaPanel, -1, u'模塊型號')
paraInput_Sizer.Add(stockCode_Text,proportion=0,flag=wx.EXPAND|wx.LEFT|wx.BOTTOM|wx.RIGHT,border=5)
paraInput_Sizer.Add(stockData_Text,proportion=0,flag=wx.EXPAND|wx.LEFT|wx.BOTTOM|wx.RIGHT,border=5)
(3) 建立wx.GridSizer佈局管理器,建立控件經過Add()方法添加至均勻分佈的二維網格中,即同一行的控件具備相同高度,同一列中控件具備相同的寬度。對RightPanel調用SetSizer()方法使佈局有效。
self.FlexGridSizer=wx.FlexGridSizer(rows=3, cols=1, vgap=3, hgap=3) self.FlexGridSizer.Add(self.Button1,proportion = 0, border = 5,flag = wx.ALL | wx.EXPAND) self.FlexGridSizer.Add(self.Button2,proportion = 0, border = 5,flag = wx.ALL | wx.EXPAND) self.FlexGridSizer.Add(self.Button3,proportion = 0, border = 5,flag = wx.ALL | wx.EXPAND) self.FlexGridSizer.SetFlexibleDirection(wx.BOTH) self.RightPanel.SetSizer(self.FlexGridSizer)
(4) ParaPanel中控件添加至縱向BoxSizer中,然後與MPL、RightPanel一同添加至橫向BoxSizer以實現嵌套佈局。Add()方法中proportion爲比例控制,假如在橫向BoxSizer中兩個控件的proportion相等,那麼Frame尺寸橫向改變時,控件大小保持相同,若proportion=0則大小不變。
vboxnetA.Add(paraInput_Sizer,proportion=0,flag=wx.EXPAND|wx.LEFT|wx.BOTTOM|wx.RIGHT,border=5) vboxnetA.Add(self.IndicatInput_Box,proportion=0,flag=wx.EXPAND|wx.LEFT|wx.BOTTOM|wx.RIGHT,border=5) vboxnetA.Add(self.TextAInput,proportion=0,flag=wx.EXPAND|wx.LEFT|wx.BOTTOM|wx.RIGHT,border=5) self.ParaPanel.SetSizer(vboxnetA) self.HBoxPanel.Add(self.ParaPanel,proportion = 1, border = 2,flag = wx.ALL | wx.EXPAND) self.HBoxPanel.Add(self.MPL,proportion = 1, border = 2,flag = wx.ALL | wx.EXPAND) self.HBoxPanel.Add(self.RightPanel,proportion = 1, border = 2,flag = wx.ALL | wx.EXPAND) self.SetSizer(self.HBoxPanel)
頁面切換實現3噸叉車價格
此章節介紹在GUI界面中點擊按鈕實現主頁面的切換功能。sizer佈局器除了Add()方法外還包括Detach()方法移除控件,Insert()方法插入控件等,可支持動態佈局的實現,此處在按鈕事件任務中動態建立OptionPanel面板,使用Replace()方法替換MPL面板,經過Layout()函數強制Sizer從新繪製界面。點擊Diag按鈕後界面以下圖所示。
def Button1Event(self,event): #建立選項欄目面板 self.OptionPanel = PanelB(self) self.HBoxPanel.Hide(self.MPL) self.HBoxPanel.Replace(self.MPL,self.OptionPanel) self.SetSizer(self.HBoxPanel) self.HBoxPanel.Layout() self.ProcessPanelB()