11.3 使用其它类型的sizer [wxPython in Action]
11.3 使用其它类型的sizer
我们已经讨论了基本的sizer,现在我们可以转向更复杂和更灵 活的sizer了。其中两个(flex grid sizer和grid bag sizer)本质上是grid的变种。另外两个(box和 static box sizer)使用一个不同的和更灵活的布局结构。
11.3.1 什么是flex grid sizer?
flex grid sizer是grid sizer的一个更灵活的版本。它与标准的grid sizer几乎相同,除了下面的例外:
1、每行和每列可以有各自的尺寸。
2、默认情况下,当尺寸调整时,它不改变它的单元格的尺寸。如果需要的话,你可以指定哪行或哪列应该增长。
3、它可以在两个方向之一灵活地增长,意思是你可以为个别的子元素指定比列量,并且你可以指定固定方向上的行为。
图11.7显示了一个flex grid sizer,它的布局也是9个单元格。这里的中间单元格更大。
图11.7
![]()
与 图11.5相比较,对于相同的布局,图11.5中每个单元格的尺寸与中间对象的相同,在flex grid sizer中,单元格的尺寸大小根据它所在的 行和列来定。它们宽度是该列中宽度最大的项目的宽度,它们的高度是该行中宽度最高的项目的宽度。在这里,项目“four”和项目“six”的单元格的高度 比项目本身的高度更高,因为其同行中的项目“five”,而"two"和"seven"的单元格的宽度也更宽。“one,” “three,” “seven,” 和“nine”的单元格是正常的尺寸,并且不受较大的窗口部件的影响。
图11.8展示了当调整窗口尺寸时,flex grid sizer的默认行为——单元格的尺寸不改变。
图11.8
![]()
例11.6显示了产生了图11.8的代码
例11.6 创建一个flex grid sizer
import wx
from blockwindow import BlockWindow
labels = "one two three four five six seven eight nine".split()
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "FlexGridSizer")
sizer = wx.FlexGridSizer(rows=3, cols=3, hgap=5, vgap=5)
for label in labels:
bw = BlockWindow(self, label=label)
sizer.Add(bw, 0, 0)
center = self.FindWindowByName("five")
center.SetMinSize((150,50))
self.SetSizer(sizer)
self.Fit()
app = wx.PySimpleApp()
TestFrame().Show()
app.MainLoop()
一个flex grid sizer是wx.FlexGridSizer的一个实例。类wx.FlexGridSizer是wx.GridSizer的子类,所以wx.GridSizer的属性方法依然有效。wx.FlexGridSizer的构造函数与其父类的相同:
wx.FlexGridSizer(rows, cols, vgap, hgap)
为了当sizer扩展时,使一行或列也扩展,你需要使用适当的方法显式地告诉该sizer该行或列是可扩展的:
AddGrowableCol(idx, proportion=0)
AddGrowableRow(idx, proportion=0)
当sizer 水平扩展时,关于新宽度的默认行为被等同地分配给每个可扩展的列。同样,一个垂直的尺寸调整也被等同地分配给每个可扩展的行。要改变这个默认的行为并且使 不同的行和列有不现的扩展比率,你需要使用proportion参数。如果proportion参数被使用了,那么与该参数相关的新的空间就被分配给了相 应的行或列。例如,如果你有两个尺寸可调整的行,并且它们的proportion分别是2和1,那么这第一个行将得到新空间的2/3,第二行将得到 1/3。图11.9显示使用proportional(比列)空间的flex grid sizer。在这里,中间行和列所占的比例是2和5,两端的行和 列所占的比例是1。
图11.9
![]()
正如你可以看到的,当所有的单元格增大时,中间的行和列的增大是两端的两倍。窗口部件的没有改变尺寸以填表充它们的单元格,虽然可以通过在当它们被添加到sizer时使用wx.EXPAND来实现。例11.7显示了产生图11.9的代码。
例11.7
import wx
from blockwindow import BlockWindow
labels = "one two three four five six seven eight nine".split()
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Resizing Flex Grid Sizer")
sizer = wx.FlexGridSizer(rows=3, cols=3, hgap=5, vgap=5)
for label in labels:
bw = BlockWindow(self, label=label)
sizer.Add(bw, 0, 0)
center = self.FindWindowByName("five")
center.SetMinSize((150,50))
sizer.AddGrowableCol(0, 1)
sizer.AddGrowableCol(1, 2)
sizer.AddGrowableCol(2, 1)
sizer.AddGrowableRow(0, 1)
sizer.AddGrowableRow(1, 5)
sizer.AddGrowableRow(2, 1)
self.SetSizer(sizer)
self.Fit()
app = wx.PySimpleApp()
TestFrame().Show()
app.MainLoop()
如果你对一个可扩展的行或列使用了比例尺寸,那么你需要对该方向上的所有可扩展的行或列指定一个比例量,否则你将得到一个糟糕的效果。
在flex grid sizer 中还有另外一个机制用于控制窗口部件的增长(执不执行先前AddGrowable*方法的设置)。默认情况下,比例尺寸适用于flex grid的两个方 向;但是你可以通过使用SetFlexibleDirection(direction)方法来指定仅某个方向应该按比例调整尺寸,参数 direction的值可以是:wx.HORIZONTAL, wx.VERTICAL, 或wx.BOTH (默认值)。然后你可以使用 SetNonFlexibleGrowMode(mode)方法来指定另一个方向上的行为。例如,如果你调用了SetFlexibleDirection (wx.HORIZONTAL)方法,列的行为就遵循AddGrowableCol(),然后调用SetNonFlexibleGrowMode()来定 义行的行为。表11.3显示了mode参数的有效值。
表11.3
wx.FLEX_GROWMODE_ALL:flex grid在没有使用SetFlexibleDirection*的方向上等同地调整所有单元格的尺寸。这将覆盖使用AddGrowable*方法设置的任何行为——所有的单元格都将被调整尺寸,不管它们的比例或它们是否被指定为可扩展(增长)的。
wx.FLEX_GROWMODE_NONE:在没有使用SetFlexibleDirection*的方向上的单元格的尺寸不变化,不管它们是否被指定为可增长的。
wx.FLEX_GROWMODE_SPECIFIED:在没有使用SetFlexibleDirection*的方向上,只有那些可增长的单元格才增长。但是sizer将忽略任何的比例信息并等同地增长那些单元格。这是一个默认行为。
上 面段落中所讨论的SetFlexibleDirection和SetNonFlexibleGrowMode方法都有对应的方法: GetFlexibleDirection()和GetNonFlexibleGrowMode(),它们返回整型标记。在上表中要强调的是,任何使用这 些方法来指定的设置将取代通过AddGrowableCol()和AddGrowableRow()创建的设置。
我们已经讨论了基本的sizer,现在我们可以转向更复杂和更灵 活的sizer了。其中两个(flex grid sizer和grid bag sizer)本质上是grid的变种。另外两个(box和 static box sizer)使用一个不同的和更灵活的布局结构。
11.3.1 什么是flex grid sizer?
flex grid sizer是grid sizer的一个更灵活的版本。它与标准的grid sizer几乎相同,除了下面的例外:
1、每行和每列可以有各自的尺寸。
2、默认情况下,当尺寸调整时,它不改变它的单元格的尺寸。如果需要的话,你可以指定哪行或哪列应该增长。
3、它可以在两个方向之一灵活地增长,意思是你可以为个别的子元素指定比列量,并且你可以指定固定方向上的行为。
图11.7显示了一个flex grid sizer,它的布局也是9个单元格。这里的中间单元格更大。
图11.7

与 图11.5相比较,对于相同的布局,图11.5中每个单元格的尺寸与中间对象的相同,在flex grid sizer中,单元格的尺寸大小根据它所在的 行和列来定。它们宽度是该列中宽度最大的项目的宽度,它们的高度是该行中宽度最高的项目的宽度。在这里,项目“four”和项目“six”的单元格的高度 比项目本身的高度更高,因为其同行中的项目“five”,而"two"和"seven"的单元格的宽度也更宽。“one,” “three,” “seven,” 和“nine”的单元格是正常的尺寸,并且不受较大的窗口部件的影响。
图11.8展示了当调整窗口尺寸时,flex grid sizer的默认行为——单元格的尺寸不改变。
图11.8

例11.6显示了产生了图11.8的代码
例11.6 创建一个flex grid sizer
import wx
from blockwindow import BlockWindow
labels = "one two three four five six seven eight nine".split()
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "FlexGridSizer")
sizer = wx.FlexGridSizer(rows=3, cols=3, hgap=5, vgap=5)
for label in labels:
bw = BlockWindow(self, label=label)
sizer.Add(bw, 0, 0)
center = self.FindWindowByName("five")
center.SetMinSize((150,50))
self.SetSizer(sizer)
self.Fit()
app = wx.PySimpleApp()
TestFrame().Show()
app.MainLoop()
一个flex grid sizer是wx.FlexGridSizer的一个实例。类wx.FlexGridSizer是wx.GridSizer的子类,所以wx.GridSizer的属性方法依然有效。wx.FlexGridSizer的构造函数与其父类的相同:
wx.FlexGridSizer(rows, cols, vgap, hgap)
为了当sizer扩展时,使一行或列也扩展,你需要使用适当的方法显式地告诉该sizer该行或列是可扩展的:
AddGrowableCol(idx, proportion=0)
AddGrowableRow(idx, proportion=0)
当sizer 水平扩展时,关于新宽度的默认行为被等同地分配给每个可扩展的列。同样,一个垂直的尺寸调整也被等同地分配给每个可扩展的行。要改变这个默认的行为并且使 不同的行和列有不现的扩展比率,你需要使用proportion参数。如果proportion参数被使用了,那么与该参数相关的新的空间就被分配给了相 应的行或列。例如,如果你有两个尺寸可调整的行,并且它们的proportion分别是2和1,那么这第一个行将得到新空间的2/3,第二行将得到 1/3。图11.9显示使用proportional(比列)空间的flex grid sizer。在这里,中间行和列所占的比例是2和5,两端的行和 列所占的比例是1。
图11.9

正如你可以看到的,当所有的单元格增大时,中间的行和列的增大是两端的两倍。窗口部件的没有改变尺寸以填表充它们的单元格,虽然可以通过在当它们被添加到sizer时使用wx.EXPAND来实现。例11.7显示了产生图11.9的代码。
例11.7
import wx
from blockwindow import BlockWindow
labels = "one two three four five six seven eight nine".split()
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Resizing Flex Grid Sizer")
sizer = wx.FlexGridSizer(rows=3, cols=3, hgap=5, vgap=5)
for label in labels:
bw = BlockWindow(self, label=label)
sizer.Add(bw, 0, 0)
center = self.FindWindowByName("five")
center.SetMinSize((150,50))
sizer.AddGrowableCol(0, 1)
sizer.AddGrowableCol(1, 2)
sizer.AddGrowableCol(2, 1)
sizer.AddGrowableRow(0, 1)
sizer.AddGrowableRow(1, 5)
sizer.AddGrowableRow(2, 1)
self.SetSizer(sizer)
self.Fit()
app = wx.PySimpleApp()
TestFrame().Show()
app.MainLoop()
如果你对一个可扩展的行或列使用了比例尺寸,那么你需要对该方向上的所有可扩展的行或列指定一个比例量,否则你将得到一个糟糕的效果。
在flex grid sizer 中还有另外一个机制用于控制窗口部件的增长(执不执行先前AddGrowable*方法的设置)。默认情况下,比例尺寸适用于flex grid的两个方 向;但是你可以通过使用SetFlexibleDirection(direction)方法来指定仅某个方向应该按比例调整尺寸,参数 direction的值可以是:wx.HORIZONTAL, wx.VERTICAL, 或wx.BOTH (默认值)。然后你可以使用 SetNonFlexibleGrowMode(mode)方法来指定另一个方向上的行为。例如,如果你调用了SetFlexibleDirection (wx.HORIZONTAL)方法,列的行为就遵循AddGrowableCol(),然后调用SetNonFlexibleGrowMode()来定 义行的行为。表11.3显示了mode参数的有效值。
表11.3
wx.FLEX_GROWMODE_ALL:flex grid在没有使用SetFlexibleDirection*的方向上等同地调整所有单元格的尺寸。这将覆盖使用AddGrowable*方法设置的任何行为——所有的单元格都将被调整尺寸,不管它们的比例或它们是否被指定为可扩展(增长)的。
wx.FLEX_GROWMODE_NONE:在没有使用SetFlexibleDirection*的方向上的单元格的尺寸不变化,不管它们是否被指定为可增长的。
wx.FLEX_GROWMODE_SPECIFIED:在没有使用SetFlexibleDirection*的方向上,只有那些可增长的单元格才增长。但是sizer将忽略任何的比例信息并等同地增长那些单元格。这是一个默认行为。
上 面段落中所讨论的SetFlexibleDirection和SetNonFlexibleGrowMode方法都有对应的方法: GetFlexibleDirection()和GetNonFlexibleGrowMode(),它们返回整型标记。在上表中要强调的是,任何使用这 些方法来指定的设置将取代通过AddGrowableCol()和AddGrowableRow()创建的设置。
-*- 此文章为本人发呆时 ctrl+c , ctrl+v 的结果. 如果损害到您的利益, 可以联系我 QQ: 248078462 -*-