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