轉載
原文地址:https://www.cnblogs.com/chengxuyuan326260/p/6364703.html
wxPython布局管理
一個典型的應用程序是由不同的部件。這些小部件被放進容器部件。一個程序員必須管理應用程序的布局。這不是一項容易的任務。在wxPython我們有兩個選擇。
*absolute positioning
*sizers
Absolute Positioning絕對位置
程序員指定位置和大小的每個小部件以像素為單位。當你使用絕對定位,你必須了解一些事情。
1.如果你改變窗口大小,大小和位置的一個小部件不改變
2.在各種平台上的應用程序看起來不同
3.更改字體在您的應用程序可能會破壞布局
4.如果你決定改變你的布局,你必須完全重做你的布局,這是繁瑣又費時
可能存在的情況下,我們可能使用絕對定位。例如,我的教程。我不想使示例太難了,所以我經常使用絕對定位來解釋一個主題。但是最重要的是,在現實世界的程序,程序員使用sizer。
在我們的例子中,我們有一個簡單的文本編輯器骨架。如果我們調整窗口大小,因為我們希望wx.TextCtrl的大小不會改變。
- '''''
- Created on 2012-7-1
- @author: Administrator
- '''
- import wx
- class Example(wx.Frame):
- def __init__(self,parent,title):
- super(Example,self).__init__(parent,title=title,size=(260,180))
- self.InitUI()
- self.Centre()
- self.Show()
- def InitUI(self):
- panel = wx.Panel(self, -1)
- menuBar = wx.MenuBar()
- filem = wx.Menu()
- editm = wx.Menu()
- helpm = wx.Menu()
- menuBar.Append(filem,"&File")
- menuBar.Append(editm,"&Edit")
- menuBar.Append(helpm,"&Help")
- self.SetMenuBar(menuBar)
- wx.TextCtrl(panel,pos=(3,3),size=(250,150))
- if __name__ == '__main__':
- app = wx.App()
- Example(None,title='Layout1')
- app.MainLoop()
在上面的示例中,我們的位置文本控制在絕對坐標。
- wx.TextCtrl(panel, pos=(3, 3), size=(250, 150))
Using sizers使用sizers
Sizers do address all those issues, we mentioned by absolute positioning. We can choose among these sizers:
我們可以選擇下列sizers:
1.wx.BoxSizer
2.wx.StaticBoxSizer
3.wx.GridSizer
4.wx.FlexGridSizer
5.wx.GridBagSizer
- import wx
- class Example(wx.Frame):
- def __init__(self,parent,title):
- super(Example,self).__init__(parent,title=title,size=(260,180))
- self.InitUI()
- self.Centre()
- self.Show()
- def InitUI(self):
- menuBar = wx.MenuBar()
- filem = wx.Menu()
- editm = wx.Menu()
- helpm = wx.Menu()
- menuBar.Append(filem,"&File")
- menuBar.Append(editm,"&Edit")
- menuBar.Append(helpm,"&Help")
- self.SetMenuBar(menuBar)
- wx.TextCtrl(self)
- if __name__ == '__main__':
- app = wx.App()
- Example(None,title='Layout1')
- app.MainLoop()
在這個例子中,沒有用到sizer。我們wx.Frame的部件放在一個wx.TextCtrl。 wx.Frame的部件有一個特殊的內置SIZER。我們可以把wx.Frame的容器內,只有一個窗口。子部件占據所有的空間.
wx.BoxSizer
This sizer enables us to put several widgets into a row or a column. We can put another sizer into an existing sizer. This way we can create very complex layouts.
sizer可以放置很多部件到行或者行。也可以放置其它sizer。這樣我們可以創建非常復雜的界面。
- box = wx.BoxSizer(integer orient)
- box.Add(wx.Window window, integer proportion=0, integer flag = 0, integer border = 0)
方向可以wx.VERTICAL或wx.HORIZONTAL的。添加到wx.BoxSizer部件是通過Add()方法。為了了解它,我們需要來看看它的參數。
比例參數定義的部件,將如何定義的方向改變的比例。假設我們有三個按鈕的比例0,1和2。它們被添加成水平wx.BoxSizer。按鈕0比例不會改變。按鈕比例2比1的水平尺寸比例更將改變兩次。
與標志參數可以進一步配置在wx.BoxSizer的小部件的行為。我們可以控制的部件之間的邊界。我們添加了一些像素部件之間的空間。為了適用邊界,我們需要定義的兩側,將用於邊境。我們可以結合| e.g wx.LEFT| wx.BOTTOM。我們可以選擇這些標志:
1.wx.LEFT
2.wx.RIGHT
3.wx.BOTTOM
4.wx.TOP
5.wx.ALL
- '''''
- Created on 2012-7-2
- @author: Administrator
- '''
- import wx
- class Example(wx.Frame):
- def __init__(self,parent,title):
- super(Example,self).__init__(parent,title=title,size=(260,180))
- self.InitUI()
- self.Centre()
- self.Show()
- def InitUI(self):
- panel = wx.Panel(self)
- panel.SetBackgroundColour('#4f5049')
- vbox = wx.BoxSizer(wx.VERTICAL)
- midPan = wx.Panel(panel)
- midPan.SetBackgroundColour('#ededed')
- vbox.Add(midPan,2,wx.EXPAND|wx.ALL,40)
- panel.SetSizer(vbox)
- if __name__ == '__main__':
- app = wx.App()
- Example(None,title="Border")
- app.MainLoop()
- vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 20)
我們放在圍繞midPan面板20 PX邊界。 wx.ALL適用於所有四邊邊框大小。
如果我們使用wx.EXPAND標志,我們的部件將使用所有已分配給它的空間。最后,我們還可以定義我們的部件對齊。我們做了以下標志:
1.wx.ALIGN_LEFT
2.wx.ALIGN_RIGHT
3.wx.ALIGN_TOP
4.wx.ALIGN_BOTTOM
5.wx.ALIGN_CENTER_VERTICAL
6.wx.ALIGN_CENTER_HORIZONTAL
7.wx.ALIGN_CENTER
Go To Class
In the following example we introduce several important ideas.
在接下來的例子中,我們介紹了幾種重要的方法。
- '''''
- Created on 2012-7-2
- @author: Administrator
- '''
- import wx
- class Example(wx.Frame):
- def __init__(self,parent,title):
- super(Example,self).__init__(parent,title=title,size=(500,300))
- self.InitUI()
- self.Centre()
- self.Show()
- def InitUI(self):
- panel = wx.Panel(self)
- font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
- font.SetPointSize(9)
- vbox = wx.BoxSizer(wx.VERTICAL)
- hbox1 = wx.BoxSizer(wx.HORIZONTAL)
- st1 = wx.StaticText(panel,label='Class Name')
- st1.SetFont(font)
- hbox1.Add(st1,flag=wx.RIGHT,border=8)
- tc = wx.TextCtrl(panel)
- hbox1.Add(tc,proportion=1)
- vbox.Add(hbox1,flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP,border=10)
- vbox.Add((-1,10))
- hbox3 = wx.BoxSizer(wx.HORIZONTAL)
- tc2 = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
- hbox3.Add(tc2, proportion=1, flag=wx.EXPAND)
- vbox.Add(hbox3, proportion=1, flag=wx.LEFT|wx.RIGHT|wx.EXPAND,
- border=10)
- vbox.Add((-1, 25))
- hbox4 = wx.BoxSizer(wx.HORIZONTAL)
- cb1 = wx.CheckBox(panel, label='Case Sensitive')
- cb1.SetFont(font)
- hbox4.Add(cb1)
- cb2 = wx.CheckBox(panel, label='Nested Classes')
- cb2.SetFont(font)
- hbox4.Add(cb2, flag=wx.LEFT, border=10)
- cb3 = wx.CheckBox(panel, label='Non-Project classes')
- cb3.SetFont(font)
- hbox4.Add(cb3, flag=wx.LEFT, border=10)
- vbox.Add(hbox4, flag=wx.LEFT, border=10)
- vbox.Add((-1, 25))
- hbox5 = wx.BoxSizer(wx.HORIZONTAL)
- btn1 = wx.Button(panel, label='Ok', size=(70, 30))
- hbox5.Add(btn1)
- btn2 = wx.Button(panel, label='Close', size=(70, 30))
- hbox5.Add(btn2, flag=wx.LEFT|wx.BOTTOM, border=5)
- vbox.Add(hbox5, flag=wx.ALIGN_RIGHT|wx.RIGHT, border=10)
- panel.SetSizer(vbox)
- if __name__ == '__main__':
- app = wx.App()
- Example(None,title="gotoclass")
- app.MainLoop()
布局很簡單。我們創建一個垂直sizer。然后放置五個橫的sizers。
- font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
- font.SetPointSize(9)
字體設置為9 px。
- vbox.Add(hbox3, proportion=1, flag=wx.LEFT|wx.RIGHT|wx.EXPAND,
- border=10)
- vbox.Add((-1, 25))
我們已經知道,我們可以控制部件之間的距離相結合的與邊境參數標志參數。但有一個約束條件。在Add()方法,我們可以指定只為一個邊界的所有各方。在我們的例子中,我們給10px的右側和左側。但是,如果省略wx.BOTTOM,我們不能給25 PX至底部。我們能做的是給10px底部,或0px。因此,如果我們需要不同的值,我們可以添加一些額外的空間。 Add()方法,我們可以插入25px的空白空間。
- vbox.Add(hbox5, flag=wx.ALIGN_RIGHT|wx.RIGHT, border=10)
我們放置在窗口右側的兩個按鈕。怎么對齊呢?proportion必須為0,按鈕尺寸也不能改變,我們不能指定wx.EXPAND參數。那么我們指定wx.ALIGN_RIGHT與wx.RIGHT。
wx.GridSizer
wx.GridSizer是一個二維表格,每個表格大小相同。
- wx.GridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0)
在構造函數中,我們指定數量的行和列的表。和垂直和水平表格之間的空間。
下邊是一個不完美的計算器示例:
- '''''
- Created on 2012-7-2
- @author: Administrator
- '''
- import wx
- class Example(wx.Frame):
- def __init__(self,parent,title):
- super(Example,self).__init__(parent,title=title,size=(300,250))
- self.InitUI()
- self.Centre()
- self.Show()
- def InitUI(self):
- menubar = wx.MenuBar()
- fileMenu = wx.Menu()
- menubar.Append(fileMenu,"&File")
- self.SetMenuBar(menubar)
- vbox = wx.BoxSizer(wx.VERTICAL)
- self.display = wx.TextCtrl(self,style=wx.TE_RIGHT)
- vbox.Add(self.display,flag=wx.EXPAND|wx.TOP|wx.BOTTOM,border=5)
- gs = wx.GridSizer(4,4,5,5)
- gs.AddMany( [(wx.Button(self, label='Cls'), 0, wx.EXPAND),
- (wx.Button(self, label='Bck'), 0, wx.EXPAND),
- (wx.StaticText(self), wx.EXPAND),
- (wx.Button(self, label='Close'), 0, wx.EXPAND),
- (wx.Button(self, label='7'), 0, wx.EXPAND),
- (wx.Button(self, label='8'), 0, wx.EXPAND),
- (wx.Button(self, label='9'), 0, wx.EXPAND),
- (wx.Button(self, label='/'), 0, wx.EXPAND),
- (wx.Button(self, label='4'), 0, wx.EXPAND),
- (wx.Button(self, label='5'), 0, wx.EXPAND),
- (wx.Button(self, label='6'), 0, wx.EXPAND),
- (wx.Button(self, label='*'), 0, wx.EXPAND),
- (wx.Button(self, label='1'), 0, wx.EXPAND),
- (wx.Button(self, label='2'), 0, wx.EXPAND),
- (wx.Button(self, label='3'), 0, wx.EXPAND),
- (wx.Button(self, label='-'), 0, wx.EXPAND),
- (wx.Button(self, label='0'), 0, wx.EXPAND),
- (wx.Button(self, label='.'), 0, wx.EXPAND),
- (wx.Button(self, label='='), 0, wx.EXPAND),
- (wx.Button(self, label='+'), 0, wx.EXPAND) ])
- vbox.Add(gs,proportion=1,flag=wx.EXPAND)
- self.SetSizer(vbox)
- if __name__ == '__main__':
- app = wx.App()
- Example(None,title="caculator")
- app.MainLoop()
我們用wx.StaticText控件在 Bck 與 Close之間做了個空白。然后用AddMany()方法
- gs.AddMany( [(wx.Button(self, label='Cls'), 0, wx.EXPAND),
- ...
控件按順序依次放入表格,第一行填滿后,繼續第二行。
wx.FlexGridSizer
這SIZER類似wx.GridSizer。它也有二維表的部件。但它增加了一些靈活性。 wx.GridSizer表格是相同的大小。在wx.FlexGridSizer 所有的行和列的不一定是相同的高度或寬度。
- wx.FlexGridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0)
rows和cols指定行和列的數目。 VAP和HAP添加一些在兩個方向上的小部件之間的空間。
很多時候,開發商要開發用於數據輸入和修改的對話框。我覺得這樣一個任務wx.FlexGridSizer合適。開發人員可以很容易地建立一個對話窗口,因為約束,每個單元必須具有相同的大小。
- '''''
- Created on 2012-7-2
- @author: Administrator
- '''
- import wx
- class Example(wx.Frame):
- def __init__(self,parent,title):
- super(Example,self).__init__(parent,title=title,size=(300,250))
- self.InitUI()
- self.Centre()
- self.Show()
- def InitUI(self):
- panel = wx.Panel(self)
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- fgs = wx.FlexGridSizer(3,2,9,25)
- title = wx.StaticText(panel,label='Title:')
- author = wx.StaticText(panel,label='Author:')
- review = wx.StaticText(panel,label='Review')
- tc1 = wx.TextCtrl(panel)
- tc2 = wx.TextCtrl(panel)
- tc3 = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
- fgs.AddMany([(title),(tc1,1,wx.EXPAND),(author),
- (tc2,1,wx.EXPAND),(review,1,wx.EXPAND),(tc3,1,wx.EXPAND)])
- fgs.AddGrowableRow(2,1)
- fgs.AddGrowableCol(1,1)
- hbox.Add(fgs,proportion=1,flag=wx.ALL|wx.EXPAND,border=15)
- panel.SetSizer(hbox)
- if __name__ == '__main__':
- app = wx.App()
- Example(None,title="FlexGridSizer.py")
- app.MainLoop()
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- ...
- hbox.Add(fgs, proportion=1, flag=wx.ALL|wx.EXPAND, border=15)
我們建立了一個橫向的hbox,周圍放置15px的空白。
- fgs.AddMany([(title), (tc1, 1, wx.EXPAND), (author),
- (tc2, 1, wx.EXPAND), (review, 1, wx.EXPAND), (tc3, 1, wx.EXPAND)])
然后用 AddMany() 這個方法。
- fgs.AddGrowableRow(2, 1)
- fgs.AddGrowableCol(1, 1)
我們創建一個可自動伸縮的三行兩列,前兩個文本控件將在水平方向上伸縮,第三個將在兩個方向伸縮。不要忘記,使用部件的擴展(wx.EXPAND),以使其真正發揮作用。
wx.GridBagSizer
在wxPython中最復雜Sizer要屬它了。許多程序員發現很難使用。這樣sizer是不是只對wxPython的典型,其它語言也有它。即使它是比較復雜,也不難攻克。
wx.GridBagSizer有一個簡單的構造:
- wx.GridBagSizer(integer vgap, integer hgap)
子控件之間用垂直與水平定義,然后用Add()方法添加:
- Add(self, item, tuple pos, tuple span=wx.DefaultSpan, integer flag=0,
- integer border=0, userData=None)
插入表格中的控件,有pos指定位置,(0,0)表標左上方的表格。span(跨度)為可選。下面兩種方法可以伸縮:
- AddGrowableRow(integer row)
- AddGrowableCol(integer col)
- '''''
- Created on 2012-7-2
- @author: Administrator
- '''
- import wx
- class Example(wx.Frame):
- def __init__(self,parent,title):
- super(Example,self).__init__(parent,title=title,size=(320,130))
- self.InitUI()
- self.Centre()
- self.Show()
- def InitUI(self):
- panel = wx.Panel(self)
- sizer = wx.GridBagSizer(4,4)
- text = wx.StaticText(panel,label='Rename to')
- sizer.Add(text,pos=(0,0),flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=5)
- tc = wx.TextCtrl(panel)
- sizer.Add(tc,pos=(0,1),span=(1,5),flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=5)
- buttonOK = wx.Button(panel,label='OK',size=(90,28))
- buttonClose = wx.Button(panel,label='Close',size=(90,28))
- sizer.Add(buttonOK,pos=(3,3))
- sizer.Add(buttonClose,pos=(3,4),flag=wx.RIGHT|wx.BOTTOM,border=5)
- sizer.AddGrowableRow(2)
- sizer.AddGrowableCol(1)
- panel.SetSizerAndFit(sizer)
- if __name__ == '__main__':
- app = wx.App()
- Example(None,title="FlexGridSizer.py")
- app.MainLoop()
我們必須把它看作是一個大的網格狀的表
- text = wx.StaticText(panel, label="Rename To")
- sizer.Add(text, pos=(0, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
“Rename To”這個標簽設置在左上角(0,0)位置,然后在它上、左、下旋轉5pix 的空白。
- tc = wx.TextCtrl(panel)
- sizer.Add(tc, pos=(1, 0), span=(1, 5),
- flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)
wx.TextCtrl放置在(1,0)這個位置,然后有個(1,5)的跨度,在它左、右放置5pix的空白,並且wx.EXPAND可伸展。
- sizer.Add(buttonOk, pos=(3, 3))
- sizer.Add(buttonClose, pos=(3, 4), flag=wx.RIGHT|wx.BOTTOM, border=5)
第四行放置兩個按鈕,第三行為空。注意:我們並沒有在兩個按鈕之間設置空隙。wx.GridBagSizer創建之處,各個控件之間已經有空隙了。
- sizer.AddGrowableCol(1)
- sizer.AddGrowableRow(2)

- '''''
- Created on 2012-7-2
- @author: Administrator
- '''
- import wx
- class Example(wx.Frame):
- def __init__(self,parent,title):
- super(Example,self).__init__(parent,title=title,size=(450,350))
- self.InitUI()
- self.Centre()
- self.Show()
- def InitUI(self):
- panel = wx.Panel(self)
- sizer = wx.GridBagSizer(5,5)
- text1 = wx.StaticText(panel,label="Java Class")
- sizer.Add(text1, pos=(0,0),flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=15)
- icon = wx.StaticBitmap(panel,bitmap=wx.Bitmap("exit.png"))
- sizer.Add(icon,pos=(0,4),flag=wx.TOP|wx.RIGHT|wx.ALIGN_RIGHT,border=5)
- line = wx.StaticLine(panel)
- sizer.Add(line,pos=(1,0),span=(1,5),flag=wx.EXPAND|wx.BOTTOM,border=10)
- text2 = wx.StaticText(panel,label="Name")
- sizer.Add(text2,pos=(2,0),flag=wx.LEFT,border=10)
- tc1 = wx.TextCtrl(panel)
- sizer.Add(tc1,pos=(2,1),span=(1,3),flag=wx.TOP|wx.EXPAND)
- text3 = wx.StaticText(panel, label="Package")
- sizer.Add(text3, pos=(3, 0), flag=wx.LEFT|wx.TOP, border=10)
- tc2 = wx.TextCtrl(panel)
- sizer.Add(tc2, pos=(3, 1), span=(1, 3), flag=wx.TOP|wx.EXPAND,
- border=5)
- button1 = wx.Button(panel, label="Browse...")
- sizer.Add(button1, pos=(3, 4), flag=wx.TOP|wx.RIGHT, border=5)
- text4 = wx.StaticText(panel, label="Extends")
- sizer.Add(text4, pos=(4, 0), flag=wx.TOP|wx.LEFT, border=10)
- combo = wx.ComboBox(panel)
- sizer.Add(combo, pos=(4, 1), span=(1, 3),
- flag=wx.TOP|wx.EXPAND, border=5)
- button2 = wx.Button(panel, label="Browse...")
- sizer.Add(button2, pos=(4, 4), flag=wx.TOP|wx.RIGHT, border=5)
- sb = wx.StaticBox(panel, label="Optional Attributes")
- boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
- boxsizer.Add(wx.CheckBox(panel, label="Public"),
- flag=wx.LEFT|wx.TOP, border=5)
- boxsizer.Add(wx.CheckBox(panel, label="Generate Default Constructor"),
- flag=wx.LEFT, border=5)
- boxsizer.Add(wx.CheckBox(panel, label="Generate Main Method"),
- flag=wx.LEFT|wx.BOTTOM, border=5)
- sizer.Add(boxsizer, pos=(5, 0), span=(1, 5),
- flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT , border=10)
- button3 = wx.Button(panel, label='Help')
- sizer.Add(button3, pos=(7, 0), flag=wx.LEFT, border=10)
- button4 = wx.Button(panel, label="Ok")
- sizer.Add(button4, pos=(7, 3))
- button5 = wx.Button(panel, label="Cancel")
- sizer.Add(button5, pos=(7, 4), span=(1, 1),
- flag=wx.BOTTOM|wx.RIGHT, border=5)
- sizer.AddGrowableCol(2)
- panel.SetSizer(sizer)
- if __name__ == '__main__':
- app = wx.App()
- Example(None,title="Newclass.py")
- app.MainLoop()
這是一個復雜的布局.我們同時用了wx.GridBagSizer 和 wx.StaticBoxsizer.
- line = wx.StaticLine(panel)
- sizer.Add(line, pos=(1, 0), span=(1, 5),
- flag=wx.EXPAND|wx.BOTTOM, border=10)
這是一條線,用於單獨的組內的小部件的布局。
- icon = wx.StaticBitmap(panel, bitmap=wx.Bitmap('exec.png'))
- sizer.Add(icon, pos=(0, 4), flag=wx.TOP|wx.RIGHT|wx.ALIGN_RIGHT,
- border=5)
我們把wx.StaticBitmap圖標控件放在右邊的行。
- sb = wx.StaticBox(panel, label="Optional Attributes")
- boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
wxStaticBoxSizer 像一個普通的wx.BoxSizer,但它會添加一個靜態框。