wxpython制作表格界面_wxpython入门第二步(布局)
一個典型的應用程序由各種小組件組成。這些組件被放置在容器里面。程序員必須管理應用程序的布局。在 wxPython 中,可以使用絕對定位或使用 sizer 來布局小組件。
絕對定位
程序員以像素為單位指定每個小組件的位置和大小。絕對定位有幾個缺點。如果我們調整窗口的大小,小組件的大小和位置不會改變。
應用程序在不同平臺上的外觀不同。
改變應用程序中的字體可能會破壞布局。
如果要改變布局,則必須完全重做布局,這是繁瑣和耗時的
在有些情況下,我們可能會使用絕對定位。例如,小的測試例子。但大多數情況下,程序員都會使用sizer。
在我們的例子中,我們有一個簡單的文本編輯器的骨架。如果我們調整窗口的大小,out wx.TextCtrl的大小并沒有像我們期望的那樣改變。# absolute.py
#absolute.py
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title,
size=(350, 300))
self.InitUI()
self.Centre()
def InitUI(self):
self.panel = wx.Panel(self)
self.panel.SetBackgroundColour("white")
self.LoadImages()
self.mincol.SetPosition((20, 20))
self.bardejov.SetPosition((40, 160))
self.rotunda.SetPosition((170, 50))
def LoadImages(self):
self.mincol = wx.StaticBitmap(self.panel, wx.ID_ANY,
wx.Bitmap("icon_1.png", wx.BITMAP_TYPE_ANY))
self.bardejov = wx.StaticBitmap(self.panel, wx.ID_ANY,
wx.Bitmap("icon_2.png", wx.BITMAP_TYPE_ANY))
self.rotunda = wx.StaticBitmap(self.panel, wx.ID_ANY,
wx.Bitmap("icon_3.png", wx.BITMAP_TYPE_ANY))
def main():
app = wx.App()
ex = Example(None, title='Absolute positioning')
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
在上面的例子中,我們使用絕對坐標定位三個圖像。self.mincol.SetPosition((20, 20))
通過SetPosition()方法,我們將圖像放置在x=20,y=20坐標處。
使用sizer
Sizer確實解決了我們提到的所有絕對定位的問題,wxPython有以下sizer。wx.BoxSizer
wx.StaticBoxSizer
wx.GridSizer
wx.FlexGridSizer
wx.GridBagSizer
wx.BoxSizer
wx.BoxSizer 使我們能夠將多個小組件放入一行或一列中。我們可以將另一個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中添加widget是通過Add()方法完成的。為了理解它,我們需要看看它的參數。
proportion參數定義了widgets在定義的方向上的變化比例。假設我們有三個比例為0、1和2的按鈕。它們被添加到一個水平的wx.BoxSizer.Button中。比例為0的按鈕完全不會改變。比例2的按鈕在水平維度上會比比例1的按鈕多變化一倍。
通過flag參數,可以進一步配置wx.BoxSizer中組件的行為。我們可以控制組件之間的邊界。我們在組件之間添加一些空間,單位是像素。為了應用border,我們需要定義border。我們可以用 | 操作符來組合它們,例如 wx.LEFT | wx.BOTTOM。我們可以在這些標志中進行選擇。wx.LEFT
wx.RIGHT
wx.BOTTOM
wx.TOP
wx.ALL
通過setSizer()方法對面板組件設置sizer。#border.py
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title)
self.InitUI()
self.Centre()
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, wx.ID_ANY, wx.EXPAND | wx.ALL, 20)
panel.SetSizer(vbox)
def main():
app = wx.App()
ex = Example(None, title='Border')
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
在上面的例子中,我們在一個panel周圍放置了邊框。vbox.Add(midPan, wx.ID_ANY, wx.EXPAND | wx.ALL, 20)
在border.py中,我們已經在midPan面板周圍放置了一個20 px的邊框,wx.ALL將邊框大小應用于所有四邊。
如果我們使用wx.EXPAND標志,我們的組件將使用所有分配給它的空間。最后,我們還可以定義組件的對齊方式。通過以下標志來實現。wx.ALIGN_LEFT
wx.ALIGN_RIGHT
wx.ALIGN_TOP
wx.ALIGN_BOTTOM
wx.ALIGN_CENTER_VERTICAL
wx.ALIGN_CENTER_HORIZONTAL。
wx.ALIGN_CENTER
類的例子
介紹一些重要的思想#go_to_class.py
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title)
self.InitUI()
self.Centre()
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))
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
st2 = wx.StaticText(panel, label='Matching Classes')
st2.SetFont(font)
hbox2.Add(st2)
vbox.Add(hbox2, flag=wx.LEFT | 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)
def main():
app = wx.App()
ex = Example(None, title='Go To Class')
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
布局很簡單。我們創建一個垂直的定標器。然后在其中放入五個水平縮放器。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))
我們已經知道,我們可以通過結合flag參數和border參數來控制部件之間的距離。但是有一個真正的限制。在Add()方法中,我們只能為所有給定的邊指定一個邊框。在我們的例子中,我們給右邊和左邊各10 px。但是我們不能給底部增加25 px的邊框,我們可以做的是給右邊和左邊增加10 px的邊框。我們可以做的是給底部10 px,如果省略wx.BOTTOM,則給底部0 px。所以如果我們需要不同的值,我們可以增加一些額外的空間。通過Add()方法,我們也可以插入組件和空間。vbox.Add(hbox5, flag=wx.ALIGN_RIGHT|wx.RIGHT, border=10)
我們將兩個按鈕放在窗口的右側。要做到這一點,有三件事情很重要:porportion,align和 wx.EXPAND 標志。porportion必須為零。當我們調整窗口大小時,按鈕的大小不應改變。我們不能指定wx.EXPAND標志。按鈕只復制分配給它們的區域。最后,我們必須指定wx.ALIGN_RIGHT標志。水平縮放器從窗口的左邊擴展到右邊。所以如果我們指定wx.ALIGN_RIGHT標志,按鈕就會被放置在右邊。
wx.GridSizer
wx.GridSizer在二維表格中布置組件。表格中的每個單元格都有相同的大小。wx.GridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0)
在構造函數中,我們指定表格中的行數和列數,以及單元格之間的垂直和水平空間。
在我們的例子中,我們創建了一個計算器的骨架。#calculator.py
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title)
self.InitUI()
self.Centre()
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=4)
gs = wx.GridSizer(5, 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)
def main():
app = wx.App()
ex = Example(None, title='Calculator')
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
請注意,我們是如何在Bck和Close按鈕之間放置一個空格的。我們只是在那里放了一個空的wx.StaticText。
在我們的例子中,我們使用了AddMany()方法。它是一個方便的方法,用于一次添加多個組件。gs.AddMany( [(wx.Button(self, label='Cls'), 0, wx.EXPAND),
...
組件按照添加順序放置在表格內。第一行先填,然后第二行...。
wx.FlexGridSizer
這個縮放器類似于wx.GridSizer。它也是在一個二維的表格中布置它的部件,它增加了一些靈活性。wx.GridSizer的單元格大小相同。wx.FlexGridSizer中的所有單元格在一行中具有相同的高度。在一列中,所有的單元格都有相同的寬度。但所有的行和列不一定是相同的高度或寬度。wx.FlexGridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0)
vgap和hgap在兩個方向上增加了一些部件之間的空間。
很多時候,開發人員必須開發對話框來輸入和修改數據。我發現wx.FlexGridSizer適合這樣的任務。開發者可以很容易地用這個sizer設置一個對話框窗口。也可以用wx.GridSizer來完成這個任務,但它看起來并不好看,因為每個單元格必須有相同的大小。#review.py
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title)
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)
def main():
app = wx.App()
ex = Example(None, title='Review')
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
在上面的代碼示例中,我們用FlexGridSizer創建一個Review窗口。hbox = wx.BoxSizer(wx.HORIZONTAL)
...
hbox.Add(fgs, proportion=1, flag=wx.ALL|wx.EXPAND, border=15)
我們創建了一個水平框的大小,以便在組件表格周圍放置一些空間(15 px)。fgs.AddMany([(title), (tc1, 1, wx.EXPAND), (author),
(tc2, 1, wx.EXPAND), (review, 1, wx.EXPAND), (tc3, 1, wx.EXPAND)])
我們使用AddMany()方法為sizer添加widget。wx.FlexGridSizer和wx.GridSizer都共享這個方法。fgs.AddGrowableRow(2, 1)
fgs.AddGrowableCol(1, 1)
我們讓第三行和第二列可以增長。這樣我們就可以讓文本控件在窗口調整大小時增長。前兩個文本控件將在水平方向上增長,第三個控件將在兩個方向上增長。我們不要忘記用wx.EXPAND使組件可擴展,這樣才能使它工作。
wx.GridBagSizer
wx.GridBagSizer是wxPython中最靈活的sizer。這種sizer并不只是在wxPython中才有,我們在其他工具包中也能找到它。
這種sizer可以實現項目的顯式定位。項目也可以選擇跨越多行或多列。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)
Item是一個插入到網格中的組件。pos指定了在虛擬網格中的位置,左上角單元格的pos為(0, 0)。span是一個可選的跨度,例如(3, 2)跨度是指跨度為3行2列的部件。flag和border在前面由wx.BoxSizer討論過。當窗口被調整大小時,網格中的項目可以改變它們的大小或保持默認大小。如果我們想讓你的項目增長和縮小,我們可以使用下面兩個方法。AddGrowableRow(integer row)
AddGrowableCol(integer col)
重命名窗口示例
在第一個例子中,我們創建一個Rename窗口。它將有一個wx.StaticText、一個wx.TextCtrl和兩個wx.Button 組件。#rename.py
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title)
self.InitUI()
self.Centre()
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=(1, 0), 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=10)
sizer.AddGrowableCol(1)
sizer.AddGrowableRow(2)
panel.SetSizer(sizer)
def main():
app = wx.App()
ex = Example(None, title='Rename')
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
我們把窗口看成一個大的網格表。text = wx.StaticText(panel, label="Rename To")
sizer.Add(text, pos=(0, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=10)
"Rename To "的文字走到左上角。所以我們指定(0,0)的位置。而且我們在底部、左側、底部都加了一些空格。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列(1, 5)。而且我們在小組件的左邊和右邊放了5個像素的空間。sizer.Add(buttonOk, pos=(3, 3))
sizer.Add(buttonClose, pos=(3, 4), flag=wx.RIGHT|wx.BOTTOM, border=10)
我們在第四行中放入兩個按鈕,第三行留空,以便在wx.TextCtrl和按鈕之間留出一些空間。第三行留空,這樣我們在wx.TextCtrl和按鈕之間就有了一些空間。我們將 "Ok "按鈕放入第四行,將 "Close "按鈕放入第五行。請注意,一旦我們在一個部件上應用了一些space,它就會應用到整行。sizer.AddGrowableCol(1)
sizer.AddGrowableRow(2)
最后,我們必須做的是使我們的對話框可以調整大小。我們使第二列和第三行可以增長。現在我們可以擴大或縮小我們的窗口。試著注釋這兩行,看看會發生什么。
增加類的例子
在接下來的例子中,我們創建一個窗口,它可以在JDeveloper中找到。它是一個在Java中創建新類的窗口。#new_class.py
import wx
class Example(wx.Frame):
def __init__(self,parent,title):
super(Example,self).__init__(parent,title=title)
self.InitUI()
self.Centre()
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('icon_1.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=10)
sizer.AddGrowableCol(2)
panel.SetSizer(sizer)
sizer.Fit(self)
def main():
app=wx.App()
ex=Example(None,title="Create Java Class")
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
這是一個比較復雜的布局。我們同時使用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一樣,但它在sizer周圍添加了一個靜態框。我們將復選框放入靜態框中。
總結
以上是生活随笔為你收集整理的wxpython制作表格界面_wxpython入门第二步(布局)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python分布式爬虫系统_如何构建一个
- 下一篇: skywalking 安装_如何使用sk