使用GridBagSizer中的列填充可用空间

时间:2012-05-22 18:39:36

标签: python wxpython wxwidgets

我正在尝试创建一个对话框,其中有一些长描述,每个跟随一个带有单选按钮答案的简短问题。我正在使用GridBagSizerwxWidgets docswxPython docs)来控制我的控件,其中长描述跨越所有三列,问题和两个单选按钮的答案都在他们的自己的专栏。

enter image description here

我希望答案与右边对齐,所以在将问题的flag=wx.EXPAND添加到布局时,我已尝试传递StaticText。然而,这似乎没有达到预期的效果;第一列仍然足够大以适应最长的问题,而不是填充可用空间并将单选按钮推到右侧。

import wx

class MyDialog(wx.Dialog):
    def __init__(self, *args, **kwargs):
        wx.Dialog.__init__(self, *args, **kwargs)

        sizer = wx.GridBagSizer(5, 5)
        sizer.SetEmptyCellSize((0,0))
        sizer.AddGrowableCol(0)

        for i in range(5):
            description = wx.StaticText(self, -1, "This is a long description \
that may span several lines. Filler filler filler filler filler. More filler \
filler filler filler filler.")
            description.Wrap(500)

            question = wx.StaticText(self, -1, "Are you sure?")
            yes = wx.RadioButton(self, -1, "Yes", style = wx.RB_GROUP)
            no = wx.RadioButton(self, -1, "No")

            sizer.Add(description, (i*3, 0), (1, 3))
            sizer.Add(question, (i*3+1, 0), flag=wx.EXPAND)
            sizer.Add(yes, (i*3+1, 1))
            sizer.Add(no, (i*3+1, 2))

        self.SetSizerAndFit(sizer)
        self.Show()


app = wx.App(False)
dialog = MyDialog(None)
app.MainLoop()

我还尝试添加一个额外的spacer列,并在其上设置wx.EXPAND,但这也无济于事。我也尝试在单选按钮上设置wx.ALIGN_RIGHT,但正如预期的那样,这只会使“否”按钮与右边对齐,因为它是占据剩余可用空间的第三列

我在这里遗漏了什么吗?是否有可能在GridBagSizer扩展中有一列填充可用空间,或者我做错了吗?如果我做错了,它是否记录在任何地方?参考适当的文档会有所帮助。

2 个答案:

答案 0 :(得分:2)

我尝试使用wx.Sizer.AddStretchSpacer()填补空白来解决您的问题。 http://wxpython.org/docs/api/wx.Sizer-class.html#AddStretchSpacer

我得到了它的工作,但StretchSpacers似乎在wx.GridBagSizers中表现得很奇怪

sizer.Add(description, (i*3, 0), (1, 3))
sizer.Add(question, (i*3+1, 0), flag=wx.EXPAND)
sizer.AddStretchSpacer((i*3+1,1))
sizer.Add(yes, (i*3+1, 2), flag=wx.ALIGN_RIGHT)
sizer.Add(no, (i*3+1, 3))

请注意我需要将“是”按钮对齐到右侧。我不知道为什么会这样。无论在哪个柱子上插入拉伸垫片,我都必须将Yes按钮对齐(即使垫片已插入柱0!)。此外,“否”按钮显示在右侧太远。我不明白为什么代码表现得像这样,所有这些看起来都有点hackish所以我强烈建议你不要使用这个解决方案。

但是,使用拉伸间隔符应该允许您创建宽度相对于窗口宽度的wx.BoxSizers。这将允许您排列按钮(因为它们都是相同的宽度,拉伸垫片将它们推到右侧)。所以,就像@Mike Discoll breifly建议的那样,我重构了你的代码以使用wx.BoxSizers

class MyDialog(wx.Dialog):
    def __init__(self, *args, **kwargs):
        wx.Dialog.__init__(self, *args, **kwargs)

        sizer = wx.BoxSizer(wx.VERTICAL)

        for i in range(5):
            description = wx.StaticText(self, -1, "This is a long description \
that may span several lines. Filler filler filler filler filler. More filler \
filler filler filler filler.")
            description.Wrap(500)

            questionSizer = wx.BoxSizer(wx.HORIZONTAL)
            question = wx.StaticText(self, -1, "Are you sure?")
            yes = wx.RadioButton(self, -1, "Yes", style = wx.RB_GROUP)
            no = wx.RadioButton(self, -1, "No")

            sizer.Add(description)
            questionSizer.Add(question)
            questionSizer.AddStretchSpacer()
            questionSizer.Add(yes)
            questionSizer.Add(no)
            sizer.Add(questionSizer, flag=wx.EXPAND)

        self.SetSizerAndFit(sizer)
        self.Show()

我认为你会找到你想要的结果:

Stretch Spacer and wx.BoxSizer

请注意,您必须添加带有wx.EXPAND标志的questionSizer,因为拉伸间隔符会展开以填充未使用的区域。如果你在没有wx.EXPAND的情况下调用sizer.Add(),那么宽度被设置为默认为文本和按钮的长度(即没有额外的空间来填充拉伸间隔)。使用wx.Expand将宽度设置为sizer的宽度(由于描述,我们知道将大约500像素)

您可以围绕边框进行游戏,以便按照您喜欢的方式获得项目之间的间距。

--- --- EDIT

我刚刚尝试了一个实验,我将描述文本更改为一个非常短的字符串(远小于500像素),并且由于调用self.SetSizerAndFit()调用,生成的窗口非常小并且在视觉上令人不愉快:

Small Description without Min Size

我认为如果你明确设定尺寸确定器的尺寸以确保一致的最小宽度会更好。

[...]
width = 500 #the desired minimum width
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.SetMinSize((width,1)) #ensures sizer will be minimum width
"""NOTE: the minimum size gets recalculated when new items are added.
i.e. if height exceeds 1 pixel or if width exceeds wdith, the sizer
will recalculate the minimum size"""


for i in range(5):
    description = wx.StaticText(self, -1, "Short Description") #description is less than 500 pixels, Wrap() will have no effect.
    description.Wrap(width)
[...]

结果如下:

Small Descriptio with Min Size

答案 1 :(得分:1)

部分问题在于您使用的是SetSizerAndFit()。尝试只使用SetSizer()。这有很大帮助。就个人而言,我更喜欢嵌套BoxSizer,因为它让我可以更细致地控制我的小部件的外观。