3

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

在此处输入图像描述

我希望答案与右侧对齐,因此在将问题添加到布局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()

我也尝试过添加一个额外的间隔列,并设置wx.EXPAND它,但这也无济于事。我也尝试过设置wx.ALIGN_RIGHT单选按钮,但正如预期的那样,这只会导致“否”按钮向右对齐,因为它是第三列占用了剩余的可用空间。

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

4

2 回答 2

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))

请注意我需要如何将“是”按钮向右对齐。我不知道这是为什么。无论我将拉伸垫片插入哪一列,我都必须将“是”按钮向右对齐(即使垫片已插入第 0 列!)。此外,“否”按钮出现在右侧有点太远了。我不明白为什么代码的行为是这样的,而且这一切似乎有点骇人听闻,所以我强烈建议你不要使用这个解决方案。

但是,使用拉伸间隔应该允许您创建宽度相对于窗口宽度的 wx.BoxSizer。这将允许您排列按钮(因为它们的宽度都相同,并且拉伸垫片将它们推到右侧)。因此,就像@Mike Discoll 简要建议的那样,我重构了您的代码以使用 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 和 wx.BoxSizer

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

您可以使用边框来获得您喜欢的项目之间的间距。

- -编辑 - -

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

没有最小尺寸的小描述

我认为如果您明确设置 sizer 的大小以确保一致的最小宽度会更好。

[...]
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)
[...]

结果是:

最小尺寸的小描述

于 2012-05-23T01:01:25.803 回答
1

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

于 2012-05-22T21:37:53.110 回答