wxpython:带背景的 StaticText 垂直居中文本

wxpython: StaticText vertically centered text with background

我已经阅读了很多与此类似的问题,但我陷入困境并提出自己的问题,因为没有任何效果。基本上,我想让 wx.StaticText 的文本垂直居中,同时使用 window 调整大小时。我的理解是现有解决方案不起作用,因为我关心 StaticText 的背景,所以我不能简单地将标签本身垂直居中于 sizer 中。我还看到它需要杂乱的子类化才能拥有透明背景的 StaticText,因此将其覆盖在面板上听起来很困难。

这是一个最小的例子(在我的项目中,sizer 中还有其他几个东西):

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title='Sample')
        sizer=wx.BoxSizer(wx.VERTICAL)

        label = wx.StaticText(self, -1, 'PLEASE VERTICALLY CENTER ME ;(', style=wx.ALIGN_CENTRE | wx.ST_NO_AUTORESIZE)
        label.SetMinSize((300,300))
        label.SetBackgroundColour((255,0,0))
        sizer.Add(label, 1, wx.EXPAND | wx.ALL, 10)

        self.SetSizerAndFit(sizer)

if __name__ == '__main__':
    app=wx.App()
    frame=MyFrame()
    frame.Show()
    app.MainLoop()

尽管如此,很难接受将文本垂直居中并不简单。 使标签中的文本垂直居中的最简单方法是什么?


解法: catalin 的回答给出了必要的概念!这是遇到此问题的任何其他人的完整代码段。我在 StaticText 下方添加了一个按钮,以演示垂直尺寸调整器仍在控制之中。如果您的应用程序不需要垂直尺寸调整器,则可以将其完全删除。

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title='Sample')
        sizer=wx.BoxSizer(wx.VERTICAL) # "main" sizer

        panel = wx.Panel(self) # panel just for centering label
        panel.SetBackgroundColour((255,0,0))
        label = wx.StaticText(panel, -1, 'PLEASE VERTICALLY CENTER ME ;(', style=wx.ALIGN_CENTRE | wx.ST_NO_AUTORESIZE)
        hsizer=wx.BoxSizer(wx.HORIZONTAL) # sizer for the panel
        hsizer.Add(label, 1, wx.ALIGN_CENTER_VERTICAL)
        panel.SetSizer(hsizer)
        sizer.Add(panel, 1, wx.EXPAND)

        btn = wx.Button(self, -1, 'Button')
        sizer.Add(btn, 0, wx.EXPAND)

        self.SetSizerAndFit(sizer)


if __name__ == '__main__':
    app=wx.App()
    frame=MyFrame()
    frame.Show()
    app.MainLoop()

在 C++ 中,快速方法如下所示:

    wxPanel* p = new wxPanel(this); // you don't need to put it in a sizer if it's the only child
    p->SetBackgroundColour({ 255, 0, 0 }); // this will be inherited by children
    wxStaticText* label = new wxStaticText(p, wxID_ANY, "PLEASE VERTICALLY CENTER ME ;(");

    wxSizer* s = new wxBoxSizer(wxHORIZONTAL); // for vertical one, you'd need stretch-spacers, and could not use wxALIGN_CENTER_VERTICAL, see below
    s->Add(label, wxSizerFlags(1).Align(wxALIGN_CENTER_VERTICAL));
    p->SetSizer(s);

请注意,如果您希望文本在调整大小时换行,wxStaticText 可能无法正确调整大小,您可能需要将其替换为其他内容。

sizer 概念的另一个例子。
框架被分解成多个组成部分,每个部分都分配了相关的 sizer。
然后将组件 sizer 放入主(自身)sizer 中,将它们放在一起。
在这种情况下,组件是文本,需要居中放置,右侧有一组按钮,垂直堆叠。
显然,组件和安排不同,但将设计分解成多个部分然后组装以进行最终展示的概念保持不变。
事实上,复杂的组件通常需要应用相同的原理,在最终组件之前,在主 sizer 中留下一系列子组件。

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title='Sample')
        mainsizer=wx.BoxSizer(wx.HORIZONTAL) # "main" sizer
        tsizer=wx.BoxSizer(wx.HORIZONTAL) # "text" sizer
        bsizer=wx.BoxSizer(wx.VERTICAL) # "button" sizer

        panel = wx.Panel(self) # panel for label
        button_panel = wx.Panel(self) # panel for buttons
        panel.SetBackgroundColour((190,0,0))
        button_panel.SetBackgroundColour((160,0,0))

        label = wx.StaticText(panel, -1, 'PLEASE VERTICALLY CENTER ME ;(')
        btn1 = wx.Button(button_panel,-1, 'Button 1')
        btn2 = wx.Button(button_panel,-1, 'Button 2')
        btn3 = wx.Button(button_panel,-1, 'Button 3')
        btn4 = wx.Button(button_panel,-1, 'Button 4')

        tsizer.AddSpacer(10) 
        tsizer.Add(label, 0, wx.CENTER)
        tsizer.AddSpacer(10) # Ensure gap between text and buttons

        bsizer.Add(btn1)
        bsizer.Add(btn2)
        bsizer.Add(btn3)
        bsizer.Add(btn4, 0, wx.BOTTOM, 35) # With space below

        panel.SetSizer(tsizer)
        button_panel.SetSizer(bsizer)

        mainsizer.Add(panel, proportion=1, flag=wx.EXPAND) # panel to grow when resized
        mainsizer.Add(button_panel, proportion=0, flag=wx.EXPAND) # panel to fill available space

        self.SetSizerAndFit(mainsizer)

if __name__ == '__main__':
    app=wx.App()
    frame=MyFrame()
    frame.Show()
    app.MainLoop()