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

Posted

技术标签:

【中文标题】在 wxPython 中,如何使用 sizers 在滑块下方左右对齐静态文本?【英文标题】:In wxPython, how can I use sizers to left- and right-justify statictext beneath a slider? 【发布时间】:2021-12-21 00:39:00 【问题描述】:

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

大方块是 wxGrid,小方块是 wxButton,它们都表现得很好。左图是一个 wxSlider,在滑块的每一端下方都有文本标签“慢”和“快”。

所以我布置了一堆 BoxSizer,如下所示:

由外而内:

蓝色是垂直的,包含一个 wxGrid 和绿色的 BoxSizer 绿色是水平的,包含橙色 BoxSizer 和两个按钮 橙色是垂直的,包含一个 wxSlider 和紫色 BoxSizer Purple 是水平的,包含两个 StaticText,分别是“slow”和“fast”

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

我搞砸了对齐和扩展,我读过很多其他人抱怨 BoxSlider 的帖子,但我一无所获。当我读到有关 wx.ST_NO_AUTORESIZE 的信息时,我以为我肯定拥有它,但这并没有做任何事情。我什至用 wxGlade 重建了我的窗口,得到了同样的结果,尤其是在最左边的静态文本。

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

但是我没有想法,我什至没有找到一个很好的例子,只是类似的挫败感。 如何让我的滑块占据橙色 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()

【问题讨论】:

您能否发布有关如何创建滑块以及如何将其添加到 sizer 的代码?还有你正在尝试的 wxPython 版本和操作系统是什么? @Igor,是的 - 刚才发布了代码。我正在运行 Win10、Python 3.9.2 和 wxPython 4.1.1 你试过orange_sizer.Add(slider, 1, wx.EXPAND) @Igor - 当我将几行更改为:orange_sizer.Add(slider, 1, wx.EXPAND); orange_sizer.Add(purple_sizer, 1, wx.EXPAND) 时,至少让我的滑块成为橙色尺寸器的整个宽度。没有这两项更改就无法工作,并且仍然无法修复文本。因为我不知道如何在这个框中放一个 \n,所以我给了 Python 一个假想的分号 :) 【参考方案1】:

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

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

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

【讨论】:

@RolfofSaxony 你说的“这个”是什么意思?您当然应该阅读完整的答案,您会看到第一句话暗示了可用的标签,而其余部分是关于 OP 的确切代码。 您说的完全正确,我毫无保留地道歉。您正在使用我没有发现的AddStretchSpacer。我不记得它是何时添加的,但正如您所见,我仍在使用旧的解决方法(-1,-1) 来达到相同的结果。接受我的投票。 我看了wxSL_MIN_MAX_LABELS;我没有看到使用它来应用文本标签的方法,只有我分配给滑块的最小值和最大值。 代码成功了!而且我想我明白它在做什么,在添加 AddStretchSpacer 和将参数更改为基于 wx.SizerFlags() 之间。唯一在第一次尝试时不起作用的是 Border(8);有些东西抛出了一个关于想要向 Borders 提供额外方向参数的异常。将 wx.ALL 添加到参数中就可以了。【参考方案2】:

正如@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)

【讨论】:

在 1D boxsizer 方向中使用对齐 从不 起作用,只是它在以前的 wx 版本中被默默地忽略了,但现在给出了断言失败。希望这将有助于消除对此的困惑。 @VZ。很高兴知道,干杯!

以上是关于在 wxPython 中,如何使用 sizers 在滑块下方左右对齐静态文本?的主要内容,如果未能解决你的问题,请参考以下文章

wxpython的布局方式

wxPython常用控件

wxGlade 布局中若干参数的含义

wxPython 和 STC 边距 - 顶部和底部

wxpython 布局管理

wxPython应用心得