在 wxPython 中,如何使用 sizer 左右对齐滑块下方的静态文本?

In wxPython, how can I use sizers to left- and right-justify statictext beneath a slider?

我正在尝试制作这样的 GUI:

大方块是wxGrid,小方块是wxButtons,都很好用。左边的图是一个 wxSlider,在滑块的每一端下面都有文本标签“慢”和“快”。

所以我布置了一堆 BoxSizers,像这样:

从外到内:

但我能得到的最接近渲染的是这个。 特别要注意滑块是多么的小,而且慢速和快速标签(用于标记滑块的末端!)一团糟。

我搞砸了对齐和扩展,我读了很多其他人抱怨 BoxSliders 的帖子,但我一无所获。当我读到有关 wx.ST_NO_AUTORESIZE 的内容时,我以为我肯定拥有它,但那并没有做任何事情。我什至用 wxGlade 重建了我的 window,得到了同样的东西,尤其是静态文本放在最左边。

我还没有做的一件事是以像素为单位指定任何内容的大小。似乎任何布局都不需要这样做,因为谁知道我将 运行 放在什么尺寸的屏幕上或合理的像素数是多少。如果我在 sizer 中正确理解了比例,我就不必以像素为单位指定尺寸。

但我没有想法,我什至没有找到一个很好的例子,只是类似的挫败感。 如何让我的滑块占据橙色 boxsizer 的整个宽度,以及如何让慢速和快速文本标记滑块的末端?

我是什么 运行,剥离了布局要素(并且它有滑块和标签问题):

import wx
import wx.grid

app = wx.App()

frame = wx.Frame(None, title="MyUnhappyLayout")

blue_sizer = wx.BoxSizer(wx.VERTICAL)

grid = wx.grid.Grid(frame)

blue_sizer.Add(grid, 6, wx.EXPAND, 8)

green_sizer = wx.BoxSizer()
blue_sizer.Add(green_sizer, 1, wx.EXPAND)

button1 = wx.Button(frame)
button2 = wx.Button(frame)

slider = wx.Slider(frame, name="Speed", value=1, minValue=1, maxValue=100)

purple_sizer = wx.BoxSizer()
label_slow = wx.StaticText(frame, label="Slow")
label_fast = wx.StaticText(frame, label="Fast")
purple_sizer.Add(label_slow, wx.ALIGN_LEFT)
purple_sizer.Add(label_fast, wx.ALIGN_RIGHT)

orange_sizer = wx.BoxSizer(wx.VERTICAL)
green_sizer.Add(orange_sizer, 2)
orange_sizer.Add(slider)

orange_sizer.Add(purple_sizer, wx.EXPAND)
green_sizer.Add(button1, 1, wx.EXPAND)
green_sizer.Add(button2, 1, wx.EXPAND)

frame.SetSizerAndFit(blue_sizer)
frame.Show()

app.MainLoop()

有一个“内置”选项用于显示滑块的最小和最大标签:创建它时使用 wxSL_MIN_MAX_LABELS(除非您使用的 wxWidgets 早于 2.9.1)。

否则,对于您的特定 sizer 布局(如果您在使用之前创建每个 sizer 可能更容易查看):

purple_sizer = wx.BoxSizer()
purple_sizer.Add(label_slow)
purple_sizer.AddStretchSpacer()
purple_sizer.Add(label_fast)

orange_sizer = wx.BoxSizer(wx.VERTICAL)
# when adding to a sizer, the second argument would be proportion;
# use SizerFlags to avoid mistakenly skipping an argument
orange_sizer.Add(slider, wx.SizerFlags().Expand())
orange_sizer.Add(purple_sizer, wx.SizerFlags().Expand())

green_sizer = wx.BoxSizer()
green_sizer.Add(orange_sizer, wx.SizerFlags(1)) # no need for proportion=2, 1 should do
green_sizer.Add(button1) # you probably meant to enlarge the slider, not the buttons
green_sizer.Add(button2)

blue_sizer = wx.BoxSizer(wx.VERTICAL)
blue_sizer.Add(grid, wx.SizerFlags(1).Expand().Border(8)) # no need for proportion=6, 1 should do
blue_sizer.Add(green_sizer, wx.SizerFlags().Expand())

正如@VZ 向我指出的那样,boxsizer 中的旧 Align 在它的方向上从未工作过,但现在在 wxWidgets 的较新迭代中抛出错误。
现在,实现相同结果的 old 方法是将 dummy 条目插入 sizer 并要求扩展它们。

new 方式请看@catalin 的回答。

对您的代码所做的一些更改是表面上的,通过显式而非隐式的小部件默认值来帮助我理解什么是什么。

import wx
import wx.grid

app = wx.App()

frame = wx.Frame(None, title="MyUnhappyLayout")

blue_sizer = wx.BoxSizer(wx.VERTICAL)

grid = wx.grid.Grid(frame)

blue_sizer.Add(grid, 6, wx.EXPAND, 8)

green_sizer = wx.BoxSizer(wx.HORIZONTAL)
blue_sizer.Add(green_sizer, 1, wx.EXPAND)

button1 = wx.Button(frame)
button2 = wx.Button(frame)

slider = wx.Slider(frame, name="Speed", value=1, minValue=1, maxValue=100)

purple_sizer = wx.BoxSizer(wx.HORIZONTAL)
label_slow = wx.StaticText(frame, label="Slow")
label_fast = wx.StaticText(frame, label="Fast")
purple_sizer.Add(label_slow, 0, 0, 0)
purple_sizer.Add((-1,-1), 1, wx.EXPAND, 0)
purple_sizer.Add(label_fast, 0, 0, 0)

orange_sizer = wx.BoxSizer(wx.VERTICAL)
orange_sizer.Add(slider, 0, wx.EXPAND)
orange_sizer.Add(purple_sizer, 0, wx.EXPAND)

green_sizer.Add(orange_sizer, 2, 0, 0)
green_sizer.Add(button1, 1, wx.EXPAND)
green_sizer.Add(button2, 1, wx.EXPAND)

frame.SetSizerAndFit(blue_sizer)
frame.Show()

app.MainLoop()

注:
这是虚拟条目: purple_sizer.Add((-1,-1), 1, wx.EXPAND, 0)