锁定老帖子 主题:wxPython:布局管理器
精华帖 (0) :: 良好帖 (13) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2009-12-28
在 wxPython 有两种方法对窗口内的 widgets 进行布局: 绝对定位(Absolute Positioning) 首先必须了解一下因使用绝对定位而造成的问题: 下面的例子是一个简单编辑器的框架,使用了绝对定位布局,可以发现,当我们改变窗口大小, wx.TextCtrl 的大小并没有随之改变。 import wx class Absolute(wx.Frame): menubar = wx.MenuBar() menubar.Append(file, ‘&File’) wx.TextCtrl(panel, -1, pos=(-1, -1), size=(250, 150)) self.Centre() app = wx.App(0) 在 wx.TextCtrl 的构造函数里使用了绝对定位的参数。 使用 sizers sizers 可以解决上面使用绝对定位而造成的布局问题。下面是一些可选反对使用的 sizers: import wx class Sizer(wx.Frame): menubar = wx.MenuBar() menubar.Append(file, ‘&File’) wx.TextCtrl(self, -1) self.Centre() app = wx.App(0) 你可能会问,在上面的代码中怎么没见到任何的 sizers 对象?实际上,wx.Frame 已经内建了一个 sizer,而且,只能放置一个 widget 到 wx.Frame 上。 wx.BoxSizer 可以使放置其上的 widgets 成行或者成列排列,我们也可以放置 sizer 到另一个 sizer 上,以便于创建复杂的布局。 参数 orientation(方向)可以是 wx.VERTICAL 或者 wx.HORIZONTAL。通过 Add() 方法可以添加 widgets 到 sizer 上。proportion(比例)参数。假设我们将三个按钮添加到一个 horizontal wx.BoxSizer 上,它们的 proportions 参数分别为 0、1、2。当窗口发生改变时, proportion 参数被设置为0的按钮不会在水平方向发生改变,而被设置为2 的按钮的大小始终是设置为1的按钮的两倍。border 参数用于控制边框,可以下面的值或者它们的组合值: import wx class Border(wx.Frame): panel = wx.Panel(self, -1) midPan = wx.Panel(panel, -1) vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 20) app = wx.App() 上面的代码将为 midPan 面板的四边添加宽度为20像素的边框。 wx.EXPAND 使 widget 占据分配到的全部空间。最后,我们也可以定义 widgets 的对齐方式: 实例(Go To Class) 在下面的例子中,我们将引入几个重要的构思。 import wx class GoToClass(wx.Frame): font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT) vbox = wx.BoxSizer(wx.VERTICAL) hbox1 = wx.BoxSizer(wx.HORIZONTAL) vbox.Add((-1, 10)) hbox2 = wx.BoxSizer(wx.HORIZONTAL) vbox.Add((-1, 10)) hbox3 = wx.BoxSizer(wx.HORIZONTAL) vbox.Add((-1, 25)) hbox4 = wx.BoxSizer(wx.HORIZONTAL) vbox.Add((-1, 25)) hbox5 = wx.BoxSizer(wx.HORIZONTAL) panel.SetSizer(vbox) app = wx.App() 我们创建一个 vertical sizer,并且将5个 horizontal sizers 放置于上面。 设置窗口字体的大小为9px。 实例(Find/Replace Dialog) 下面是一个复杂的例子 ── 查找/替换对话框。 import wx class FindReplace(wx.Dialog): vbox_top = wx.BoxSizer(wx.VERTICAL) vbox = wx.BoxSizer(wx.VERTICAL) # panel1 panel1 = wx.Panel(panel, -1) panel1.SetSizer(grid1) # panel2 panel2 = wx.Panel(panel, -1) sizer21 = wx.StaticBoxSizer(wx.StaticBox(panel2, -1, ‘Direction’), orient=wx.VERTICAL) sizer22 = wx.StaticBoxSizer(wx.StaticBox(panel2, -1, ‘Scope’), orient=wx.VERTICAL) panel2.SetSizer(hbox2) # panel3 panel3 = wx.Panel(panel, -1) panel3.SetSizer(sizer3) # panel4 panel4 = wx.Panel(panel, -1) panel4.SetSizer(sizer4) # panel5 panel5 = wx.Panel(panel, -1) panel5.SetSizer(sizer5) vbox_top.Add(vbox, 1, wx.LEFT, 5) self.Centre() app = wx.App() 备注:对于 Windows 用户,请在 ShowModal() 行前加入 self.SetClientSize(panel.GetBestSize()) 行。 wx.GridSizer 这是 wx.GridSizer 的构造函数。分别定义布局表格的行列数以及行列的大小。 下面使用 wx.GridSizer 来构造一个计算器的基本骨架。 import wx class GridSizer(wx.Frame): menubar = wx.MenuBar() self.Bind(wx.EVT_MENU, self.OnClose, id=1) sizer = wx.BoxSizer(wx.VERTICAL) gs.AddMany( [(wx.Button(self, -1, 'Cls'), 0, wx.EXPAND), sizer.Add(gs, 1, wx.EXPAND) def OnClose(self, event): app = wx.App() 注意,我们在 Bck 和 Close 按钮之间放置一个空白的 wx.StaticText,这是布局上的一个有用技巧。 例子中的 AddMany() 方法可以一次过放置多个 widgets 到 sizer 上。 widgets 放置在布局表格上是按一定顺序的,先放满第一行,再放置第二行…如此类推。 wx.FlexGridSizer wx.FlexGridSizer 跟 wx.GridSizer 相似,但提供更多的灵活性。在 wx.GridSizer 中,所有的单元格都必须大小相同。而在 wx.FlexGridSizer 中,同行的单元格的高度相同,同列的单元格的宽度相同,而不同的列和行可以高宽度不同。 这是 wx.FlesGridSizer 的构造函数,跟 wx.GridSizer 的构造函数相似。 import wx class FlexGridSizer(wx.Frame): panel = wx.Panel(self, -1) hbox = wx.BoxSizer(wx.HORIZONTAL) fgs = wx.FlexGridSizer(3, 2, 9, 25) title = wx.StaticText(panel, -1, ‘Title’) tc1 = wx.TextCtrl(panel, -1) fgs.AddMany([(title), (tc1, 1, wx.EXPAND), (author), (tc2, 1, wx.EXPAND), fgs.AddGrowableRow(2, 1) hbox.Add(fgs, 1, wx.ALL | wx.EXPAND, 15) self.Centre() app = wx.App() 我们设置第三行和第二列为可变大小,这样,当窗口大小改变时,文本控件也随之改变。当然,不要忘记设置相应的 widgets 的 wx.EXPAND。 wx.GridBagSizer 这是 wxPython 中最复杂的一个 sizer,它可以精确的定位 widgets。下面是 wx.GridBagSizer 的构造函数: 通过 Add() 方法放置 widgets: pos 参数指定放置于虚拟表格的位置 ── 左上角为 (0,0)。span 参数是一个可选参数,指定 widgets 的跨度,例如,(3,2) 表示 widget 跨越 3 行 2 列。falg 和 border 参数跟 wx.BoxSizer 的相同。如果想设置可改变的表格,可以使用下面的方法: 实例(Rename dialog) 这是一个简单的示例。我们不必因为 wx.GridBagSizer 的过于复杂而担心,一旦我们理解它的原理,使用起来也会很简单的。 import wx class Rename(wx.Frame): panel = wx.Panel(self, -1) text = wx.StaticText(panel, -1, ‘Rename To’) tc = wx.TextCtrl(panel, -1) buttonOk = wx.Button(panel, -1, ‘Ok’, size=(90, 28)) sizer.AddGrowableCol(1) app = wx.App() 将文本 “Rename to”放于窗口的左上角,因此将 pos 指定为 (0,0)。 将文本输入框放于第二行的始端(1,0) ── 紧记,是用 0 开始计数的。同时文本框跨越1行5列(1,5)。 在第4行放置两个按钮(第三行我们空着),分别放于第4列和第5列。 实例(Open Resource) import wx class OpenResource(wx.Frame): panel = wx.Panel(self, -1) text1 = wx.StaticText(panel, -1, ‘Select a resource to open’) tc = wx.TextCtrl(panel, -1) text2 = wx.StaticText(panel, -1, ‘Matching resources’) list1 = wx.ListBox(panel, -1, style=wx.LB_ALWAYS_SB) text3 = wx.StaticText(panel, -1, ‘In Folders’) list2 = wx.ListBox(panel, -1, style=wx.LB_ALWAYS_SB) cb = wx.CheckBox(panel, -1, ‘Show derived resources’) buttonOk = wx.Button(panel, -1, ‘OK’, size=(90, 28)) help = wx.BitmapButton(panel, -1, wx.Bitmap(‘icons/help16.png’), style=wx.NO_BORDER) sizer.AddGrowableCol(0) self.Centre() app = wx.App() 实例(Create new class) import wx class NewClass(wx.Frame): panel = wx.Panel(self, -1) text1 = wx.StaticText(panel, -1, ‘Java Class’) icon = wx.StaticBitmap(panel, -1, wx.Bitmap(‘icons/exec.png’)) line = wx.StaticLine(panel, -1 ) text2 = wx.StaticText(panel, -1, ‘Name’) tc1 = wx.TextCtrl(panel, -1, size=(-1, 30)) text3 = wx.StaticText(panel, -1, ‘Package’) tc2 = wx.TextCtrl(panel, -1) button1 = wx.Button(panel, -1, ‘Browse…’, size=(-1, 30)) text4 = wx.StaticText(panel, -1, ‘Extends’) combo = wx.ComboBox(panel, -1, ) button2 = wx.Button(panel, -1, ‘Browse…’, size=(-1, 30)) sb = wx.StaticBox(panel, -1, ‘Optional Attributes’) button4 = wx.Button(panel, -1, ‘Ok’, size=(-1, 30)) button5 = wx.Button(panel, -1, ‘Cancel’, size=(-1, 30)) sizer.AddGrowableCol(2) app = wx.App() 注意,这里我们使用负数来设置 top border,这相当于设置 bottom border 为15px。 确保窗口的大小可以覆盖所有 widgets。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-12-31
代码贴了那么多,都没注释怎么看,能不能给个详细的说明呀?
|
|
返回顶楼 | |
发表时间:2009-12-31
详细说明可以去查看 wxpython的文档 其中有很多例子的和说明
|
|
返回顶楼 | |
发表时间:2010-01-05
顶,正想找这方面的东西。
|
|
返回顶楼 | |
发表时间:2010-01-05
wx的布局感觉稍显复杂,比较喜欢qt的布局。
|
|
返回顶楼 | |
发表时间:2010-01-07
Emy 写道 代码贴了那么多,都没注释怎么看,能不能给个详细的说明呀?
这种自释的代码再加注释就是鸡肋。 |
|
返回顶楼 | |
发表时间:2010-01-08
各种各样的GUI Framework我都用过,坦白说,还是所见即所得的东西快一点。
|
|
返回顶楼 | |
发表时间:2010-01-11
如果是快速开发的话,使用手写代码方式效率太低
不知Python 在UI方面有没有好的所见即所得的编辑器? |
|
返回顶楼 | |
发表时间:2010-01-11
HammeR 写道 如果是快速开发的话,使用手写代码方式效率太低
不知Python 在UI方面有没有好的所见即所得的编辑器? 你想要的就是qt,使用qt设计器设计好的iui文件可以转换为c++代码,python代码,java代码等。 完全的设计与逻辑分离。 |
|
返回顶楼 | |
发表时间:2010-01-15
jamiesun 写道 HammeR 写道 如果是快速开发的话,使用手写代码方式效率太低
不知Python 在UI方面有没有好的所见即所得的编辑器? 你想要的就是qt,使用qt设计器设计好的iui文件可以转换为c++代码,python代码,java代码等。 完全的设计与逻辑分离。 我记得PyQt是收钱的? |
|
返回顶楼 | |