wxPython的佈局
每一個程序都會有一個界面或者稱之爲layout、佈局,在html中,我們可能使用div,在html5中,我們或許會使用header、footer標籤。如果使用的是flex,或者可以用一個mx:VDividedBox。最方便的是C#,我們直接從工具箱裏拖出一個splitcontainer或者一個tablelayoutpanel。那麼在wxPython中,我們怎麼做呢?
1、使用wx.SplitterWindow進行佈局
我們當然可以使用wx.Panle進行佈局,又或者自己寫一個class myWindow(wx.Window),不過從我接觸wxPython的短短的時間裏,我覺得wx.SplitterWindow挺好用的
上圖是一個簡單的使用wx.SplitterWindow實現的佈局,pyCrust的界面同樣是使用了wx.SplitterWindow
以下是一個最簡單的實現,需要注意的是,如果沒有綁定事件wx.EVT_SIZE,點最大化出一個有趣的問題
# -*- coding:utf-8 -*-
'''
Created on 2013-1-6
@author: jincheng
'''
import wx
import com.jincheng.AbstractModel as jca
import com.jincheng.common as jcc
class myFrame(wx.Frame):
def __init__(self,parent,title,size):
wx.Frame.__init__(self,parent,-1,title,size = size)
self.SetBackgroundColour('white')
#佈局 size
self.width = self.Size.width
self.height = self.Size.height
self.up = self.Size.height/3*2
self.down = self.Size.height/3
self.left = self.Size.width/4
self.right = self.Size.width/4*3
#上下結構
self.spltUD = wx.SplitterWindow(self,size = size)
self.winUp = wx.Window(self.spltUD,-1,(0,0),(self.width,self.up))
self.winUp.SetBackgroundColour('red')
self.winDown = wx.Window(self.spltUD,-1,(0,self.up),(self.width,self.down))
self.winDown.SetBackgroundColour('black')
self.spltUD.SplitHorizontally(self.winUp,self.winDown,-10)
#左右結構
self.spltLF = wx.SplitterWindow(self.winUp,size = (self.width,self.up))
self.winLeft = wx.Window(self.spltLF,-1,(0,0),(self.left,self.up))
self.winLeft.SetBackgroundColour('yellow')
self.winRight = wx.Window(self.spltLF,-1,(0,self.left),(self.right,self.up))
self.winRight.SetBackgroundColour('green')
self.spltLF.SplitVertically(self.winLeft,self.winRight,-10)
#事件綁定
self.Bind(wx.EVT_SIZE,self.OnSize)
def OnSize(self,event):
size = event.Size
self.spltUD.Size=event.Size
self.spltLF.Size=(size.width,size.height - self.winDown.Size.height)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = myFrame(None,'title',(800,600))
frame.Show(True)
app.MainLoop()
2、喜歡重構不是我的錯-> _ ->
上面的代碼雖然已經能夠得到我預期的結果,但是代碼實在有夠不便。雖然我的水平很菜,但還是會忍不住要重構一下啊!!
創建一個spltOpera類用於創建splitterWindow及構成splt的兩個窗口,這兩個窗口會被放在self.windows裏,以便於在frame中使用
spltOpera類可以作爲一個common類被不斷地重用
# -*- coding:utf-8 -*-
'''
Created on 2012-12-25
@author: jincheng
@name:com.jincheng.common
'''
import wx
class spltOpera():
def __init__(self,parent,size):
self.parent = parent
self.windows = []
self.splt = wx.SplitterWindow(self.parent,size = size)
def _winBuild(self,pos,size):
win = wx.Window(self.splt,-1,pos,size)
self.windows.append(win)
def spltBuild(self,winData,bHorizon=True,sashPosition=10):
'''
winData = (((0,0),(800,600)),
(0,600),(800,200))
'''
self.winData = winData
for windata in winData:
self._winBuild(windata[0],windata[1])
if bHorizon:
self.splt.SplitHorizontally(self.windows[0],self.windows[1],sashPosition)
else:
self.splt.SplitVertically(self.windows[0],self.windows[1],sashPosition)
self.parent.Bind(wx.EVT_SIZE,self.OnSize)
return self.splt
def OnSize(self,event):
#size = event.Size
self.splt.Size = self.parent.Size
創建一個layout類,用於構建獨屬於本次實例的layout,同時在frame中調用
# -*- coding:utf-8 -*-
'''
Created on 2013-1-6
@author: jincheng
'''
import wx
import com.jincheng.AbstractModel as jca
import com.jincheng.common as jcc
class layout():
def __init__(self,parent):
self.parent = parent
self.windows = []
def layoutBuild(self):
#佈局 size
self.width = self.parent.Size.width
self.height = self.parent.Size.height
self.up = self.parent.Size.height/3*2
self.down = self.parent.Size.height/3
self.left = self.parent.Size.width/4
self.right = self.parent.Size.width/4*3
winDataUD = (((0,0),(self.width,self.up)),
((0,self.up),(self.width,self.down)))
spltOUD = jcc.spltOpera(self.parent,self.parent.Size)
self.spltUD = spltOUD.spltBuild(winDataUD)
self.windows.append(spltOUD.windows)
winDataLR = (((0,0),(self.left,self.up)),
((self.left,0),(self.right,self.up)))
spltOLR = jcc.spltOpera(spltOUD.windows[0],(self.width,self.up))
self.spltLR = spltOLR.spltBuild(winDataLR,False,-10)
self.windows.append(spltOLR.windows)
class myFrame(wx.Frame):
def __init__(self,parent,title,size):
wx.Frame.__init__(self,parent,-1,title,size = size)
_layout = layout(self)
_layout.layoutBuild()
self.winUp = _layout.windows[0][0]
self.winUp.SetBackgroundColour('green')
self.winDown = _layout.windows[0][1]
self.winDown.SetBackgroundColour('yellow')
self.winLeft = _layout.windows[1][0]
self.winLeft.SetBackgroundColour('red')
self.winRight = _layout.windows[1][1]
self.winRight.SetBackgroundColour('pink')
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = myFrame(None,'title',(800,600))
frame.Show(True)
app.MainLoop()
源碼push不到github……那就不傳了吧……
3、通過wx.Notebook添加選項卡
在C#中,我們通過拖一個TabControl完成添加選項卡的工作,在flex我們選擇mx:TabNavigator標籤。在wxPython中,可以使用wx.Notebook
wx.Notebook的init需要一個parent,一個pos,還有一個size,在這個例子中,我選擇將notebook放在winRight中
class myFrame(wx.Frame):
def __init__(self,parent,title,size):
wx.Frame.__init__(self,parent,-1,title,size = size)
_layout = layout(self)
_layout.layoutBuild()
self.winUp = _layout.windows[0][0]
self.winUp.SetBackgroundColour('green')
self.winDown = _layout.windows[0][1]
self.winDown.SetBackgroundColour('yellow')
self.winLeft = _layout.windows[1][0]
self.winLeft.SetBackgroundColour('red')
self.winRight = _layout.windows[1][1]
self.winRight.SetBackgroundColour('pink')
#ntoebook
self.notebook = wx.Notebook(self.winRight,id = -1,pos = (0,0),size = self.winRight.Size)
self.txtwork = wx.TextCtrl(self.notebook)
self.notebook.AddPage(self.txtwork,'workspace',True)
#menubar
menuO = jcc.menuOpera(self)
menuO.menubarBuild(None)
#statusbar
statusBar = self.CreateStatusBar()