当文本更改时,wxPython StaticText 不会调整大小

wxPython StaticText won't resize when text changes

我的 wxPython 代码在调整大小方面遇到了一些问题。我有一个可以显示或隐藏的 StaticText 帮助消息,消息需要根据用户模式进行更改。

默认情况下,包含 StaticText 的 BoxSizer 会在第一次显示时正确假定 StaticText 的大小,但不会在 StaticText 内容更改时重新调整大小。

我的初始代码如下所示(对于上下文,完整代码在我的 post 末尾):

        self.msg_text = wx.StaticText(self.panel, label=self.default_msg_text,
                                      style=wx.TE_CENTER | wx.EXPAND,
                                      name='help msg text’)
        self.help_msg_boxsizer.Add(self.msg_text, flag=wx.EXPAND)
        self.help_msg_boxsizer.ShowItems(False)

然后我尝试手动设置尺寸:

        self.msg_text_size = (500, 100)
        self.msg_text = wx.StaticText(self.panel, label=self.default_msg_text,
                                      style=wx.TE_CENTER | wx.EXPAND,
                                      name='help msg text',
                                      size=self.msg_text_size)
        self.help_msg_boxsizer.Add(self.msg_text, flag=wx.EXPAND)
        self.help_msg_boxsizer.ShowItems(False)

然后使用:

    self.msg_text.SetSize(new_size)
    # or
    self.help_msg_boxsizer.GetStaticBox.SetSize(new_size)

但这两条线似乎都不起作用。相反,无论如何, (500, 100) 的初始大小似乎仍然被使用。

我认为设置大小提示可能会有帮助,但似乎没有效果:

    self.help_msg_boxsizer.SetSizeHints()

最后,wx.EXPAND 的存在与否似乎没有区别。

总结一下:我想做的是适当地重新调整 self.msg_text 到显示时所需的最小尺寸。我怎样才能做到这一点?

这是 运行 我的示例的完整代码:

import wx
import sys


class GridFrame(wx.Frame):

    def __init__(self, frame_name="grid frame",
                 panel_name="grid panel", parent=None):
        title = 'Edit {} data'.format(panel_name)
        super(GridFrame, self).__init__(parent=parent, id=wx.ID_ANY,
                                        name=frame_name, title=title)
        self.remove_cols_mode = False
        self.panel = wx.Panel(self, name=panel_name)#, size=wx.GetDisplaySize())
        self.grid_type = str(panel_name)
        self.InitUI()


    ## Initialization functions
    def InitUI(self):
        """
        initialize window
        """
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
        set1 = []
        ## btns set 1
        for btn_name in ['btn1']:
            btn = wx.Button(self.panel, label=btn_name, name=btn_name)
            set1.append((btn))
        self.remove_cols_button = wx.Button(self.panel, label="Remove columns",
                                            name='remove_cols_btn')
        self.Bind(wx.EVT_BUTTON, self.on_remove_cols, self.remove_cols_button)

        ## Help message and button
        # button
        self.toggle_help_btn = wx.Button(self.panel, id=-1, label="Show help",
                                         name='toggle_help_btn')
        self.Bind(wx.EVT_BUTTON, self.toggle_help, self.toggle_help_btn)
        # message
        self.help_msg_boxsizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, name='help_msg_boxsizer'),
                                                   wx.VERTICAL)
        self.default_msg_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pulvinar, massa sit amet congue facilisis, augue nisl vehicula nulla, vel posuere ligula metus eu sapien. Nam vitae mauris nec turpis congue eleifend. Ut accumsan lorem risus, vitae scelerisque mi viverra at. In sit amet purus pretium, ultricies neque eget, ultricies enim. Aenean dignissim ornare mattis. Sed vitae consequat urna, et congue neque."
        self.msg_text_size = (500, 100)
        self.msg_text = wx.StaticText(self.panel, label=self.default_msg_text,
                                      style=wx.TE_CENTER | wx.EXPAND,
                                      name='help msg text',
                                      size=self.msg_text_size)
        self.help_msg_boxsizer.Add(self.msg_text, flag=wx.EXPAND)
        self.help_msg_boxsizer.SetSizeHints(self)
        self.help_msg_boxsizer.ShowItems(False)

        ## Add content to sizers
        self.hbox = wx.BoxSizer(wx.HORIZONTAL)
        vbox1 = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='Vbox1'), wx.VERTICAL)

        for btn in set1:
            vbox1.Add(btn, flag=wx.ALL, border=5)
        vbox1.Add(self.remove_cols_button)
        self.hbox.Add(vbox1, flag=wx.ALL, border=5)

        # add "grid"
        self.grid_box = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, name='grid container'), wx.VERTICAL)
        filler = wx.StaticBox(self.panel, wx.ID_ANY, "FillerStaticBox", size=(500, 200))
        self.grid_box.Add(filler, 1, flag=wx.ALL|wx.EXPAND, border=5)
        # final layout, set size
        self.main_sizer.Add(self.hbox, flag=wx.ALL|wx.ALIGN_CENTER|wx.SHAPED, border=20)
        self.main_sizer.AddSpacer(20)
        self.main_sizer.Add(self.toggle_help_btn, .5,
                            flag=wx.BOTTOM|wx.ALIGN_CENTRE|wx.SHAPED,
                            border=5)
        self.main_sizer.Add(self.help_msg_boxsizer, .5,
                            flag=wx.BOTTOM|wx.ALIGN_CENTRE|wx.SHAPED,
                            border=10)
        self.main_sizer.AddSpacer(10)

        self.main_sizer.Add(self.grid_box, 2, flag=wx.ALL|wx.ALIGN_CENTER|wx.EXPAND, border=10)
        self.panel.SetSizer(self.main_sizer)
        self.panel_sizer = wx.BoxSizer(wx.VERTICAL)
        self.panel_sizer.Add(self.panel, 1)
        self.SetSizer(self.panel_sizer)
        self.panel_sizer.Fit(self)
        self.Centre()
        self.Show()


    def do_fit(self, event, min_size=None):
        """
        Re-fit the window to the size of the content.
        """
        if event:
            event.Skip()
        self.panel_sizer.Fit(self)
        self.Centre()
        return

    def toggle_help(self, event, mode=None):
        """
        Show/hide help message on help button click.
        """
        # if mode == 'open', show no matter what.
        # if mode == 'close', close.  otherwise, change state
        btn = self.toggle_help_btn
        shown = self.help_msg_boxsizer.GetStaticBox().IsShown()

        # if mode is specified, do that mode
        if mode == 'open':
            self.msg_text.SetSize(self.msg_text_size)
            self.help_msg_boxsizer.GetStaticBox().SetSize(self.msg_text_size)
            #self.help_msg_boxsizer.Fit(self.msg_text)
            self.help_msg_boxsizer.ShowItems(True)
            btn.SetLabel('Hide help')
        elif mode == 'close':
            self.help_msg_boxsizer.ShowItems(False)
            btn.SetLabel('Show help')
        # otherwise, simply toggle states
        else:
            if shown:
                self.help_msg_boxsizer.ShowItems(False)
                btn.SetLabel('Show help')
            else:
                self.msg_text.SetSize(self.msg_text_size)
                self.help_msg_boxsizer.GetStaticBox().SetSize(self.msg_text_size)
                #self.help_msg_boxsizer.Fit(self.msg_text)
                self.help_msg_boxsizer.ShowItems(True)
                btn.SetLabel('Hide help')

        self.do_fit(None)


    ##  Events

    def on_remove_cols(self, event):
        """
        enter 'remove columns' mode
        """
        self.remove_cols_mode = True
        self.remove_cols_button.SetLabel("end delete column mode")
        self.remove_cols_button.SetSize(self.remove_cols_button.GetBestSize())
        # change button to exit the delete columns mode
        self.Unbind(wx.EVT_BUTTON, self.remove_cols_button)
        self.Bind(wx.EVT_BUTTON, self.exit_col_remove_mode, self.remove_cols_button)
        # then make some visual changes
        self.msg_text_size = (50, 50)
        self.msg_text.SetLabel("Remove grid columns: click on a column header to delete it.Required headers for {}s may not be deleted.".format(self.grid_type))
        self.toggle_help(event=None, mode='open')
        self.grid_box.GetStaticBox().SetWindowStyle(wx.DOUBLE_BORDER)

    def exit_col_remove_mode(self, event):
        """
        go back from 'remove cols' mode to normal
        """
        # close help messge
        self.toggle_help(event=None, mode='close')
        # update mode
        self.remove_cols_mode = False
        self.grid_box.GetStaticBox().SetWindowStyle(wx.DEFAULT)
        self.msg_text.SetLabel(self.default_msg_text)
        self.msg_text_size = (500, 150)
        self.help_msg_boxsizer.Fit(self.help_msg_boxsizer.GetStaticBox())
        self.toggle_help(None, mode='close')
        # re-bind self.remove_cols_button
        self.Bind(wx.EVT_BUTTON, self.on_remove_cols, self.remove_cols_button)
        self.remove_cols_button.SetLabel("Remove columns")
        self.do_fit(None)


if __name__ == "__main__":
    app = wx.App()
    frame = GridFrame()
    if '-i' in sys.argv:
        import wx.lib.inspection
        wx.lib.inspection.InspectionTool().Show()
    app.MainLoop()

您不需要任何这些,因为当文本更改时,只需在父级或层次结构中的一个 sizer 上调用 Layout 就足够了。

此外,我看到您在将 help_msg_boxsizer 添加到 main_sizer 时设置了 wx.SHAPED 标志。这告诉父 sizer 保持与项目首次添加到 sizer 时相同的纵横比,这可能是阻止 sizer 和静态文本的大小大于 0 像素高的原因。

最后,您在几个地方使用了 .5 的比例值。该参数是一个整数,因此它只会被截断为零,并且不会执行您可能希望它执行的操作。比例的工作方式是使用 sizer 中比例值的总和来计算空闲 space 的分配方式。例如,如果 box sizer 的项目的比例为 1、1、2,则前 2 个项目各获得 25% 的免费 space,第三个获得 50%。