wxpython: статический текст, вертикально центрированный текст с фоном

#python #wxpython #wxwidgets

#питон #wxpython #wxwidgets

Вопрос:

Я читал так много вопросов, подобных этому, но я сдаюсь и создаю свои собственные, потому что ничего не работает. В принципе, я хочу, чтобы мой wx.StaticText текст был вертикально центрирован при изменении размера окна. Я понимаю , что существующие решения не работают, потому что я забочусь о фоновом режиме StaticText , и поэтому я не могу просто вертикально центрировать саму метку в сайзере. Я также вижу, что для создания статического текста с прозрачным фоном требуется беспорядочное создание подклассов, поэтому наложение его на панель звучит сложно.

Вот минимальный пример (в моем проекте в сайзере есть еще несколько вещей):

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

Несмотря на это, трудно смириться с тем, что вертикально центрировать текст непросто. Как проще всего расположить текст на этикетке по вертикали по центру?


Решение: ответ каталина дал необходимую концепцию! Вот полный фрагмент для всех, кто сталкивается с этой проблемой. Я добавил кнопку под статическим текстом, чтобы продемонстрировать, что вертикальный размер остается под контролем. Вертикальный калибровщик может быть полностью удален, если он не нужен вашему приложению.

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

Комментарии:

1. почему вам нужно wxEXPAND | wxALL? , не можете ли вы использовать wxEXPAND | wxALIGN_CENTER_VERTICAL ?

2. @Игорь, Насколько я понимаю, это разные вещи. wx.ВСЕ просто означает, что мне нужна граница, это не важная деталь. Однако самое главное, что ALIGN_CENTER_VERTICAL выровняет саму метку, а не текст внутри метки. Это также несовместимо с wx.EXPAND (если метка занимает все возможное пространство, то для ее выравнивания/центрирования нет места).

Ответ №1:

В c быстрый способ выглядел бы так:

 wxPanel* p = new wxPanel(this); // you don't need to put it in a sizer if it's the only child  p-gt;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-gt;Add(label, wxSizerFlags(1).Align(wxALIGN_CENTER_VERTICAL));  p-gt;SetSizer(s);  

Имейте в виду, что если вы хотите, чтобы текст был перенесен при изменении размера, wxStaticText он, вероятно, будет изменен неправильно, и вам, возможно, потребуется заменить его чем-то другим.

Комментарии:

1. Спасибо!! Концепция сработала идеально. Я добавил решение на Python к этому вопросу.

Ответ №2:

Еще один пример концепции сайзера.
Рамка разбита на составные части, каждой части присвоен соответствующий размер.
Затем размеры компонентов помещаются в основной (самостоятельный) размер, чтобы собрать все это вместе.
В этом случае компоненты представляют собой текст, который необходимо центрировать, и набор кнопок справа, расположенных вертикально.
Очевидно, что компоненты и компоновка различаются, но концепция разделения дизайна на части, которые затем собираются для окончательной презентации, остается прежней.
Действительно, сложные компоненты часто нуждаются в применении одного и того же принципа, в результате чего у вас остается ряд сборок перед окончательной сборкой в главном калибраторе.

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

введите описание изображения здесь