添加新项目时在次要方向上扩展 wxWrapSizer

expand wxWrapSizer on secondary direction when adding new items

我有一个包含按钮列表的面板。按钮的数量在运行时发生变化(由于用户在别处的操作)。我使用 wxWrapSizer 来管理这些按钮,因为我希望此面板的高度保持不变,并在超出垂直方向时创建第二列按钮 space。高度由父 sizer 根据其他小部件高度管理。这几乎可以正常工作,但是直到 window 手动调整大小后才会出现第二列按钮。

我创建了一个最小示例来重现该问题:

import wx

start_buttons = 5

class ButtonsPanel(wx.Panel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.SetSizer(wx.WrapSizer(wx.VERTICAL))
        for i in range(start_buttons):
            self.add_button()

    def add_button(self):
        self.GetSizer().Add(wx.Button(self, label='foo'),
                            wx.SizerFlags().Expand())


class MyPanel(wx.Panel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # hardcoded size for sake of example only
        add_button = wx.Button(self, label="add", size=(80, 250))
        add_button.Bind(wx.EVT_BUTTON, self.OnAddButton)

        self.buttons_panel = ButtonsPanel(self)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(add_button)
        sizer.Add(self.buttons_panel, wx.SizerFlags().Expand())
        self.SetSizer(sizer)

    def OnAddButton(self, evt):
        self.buttons_panel.add_button()
        self.buttons_panel.Layout()


class MyFrame(wx.Frame):
    def __init__(self, *args):
        super().__init__(*args)
        panel = MyPanel(self)


app = wx.App()
frame = MyFrame(None)
frame.Show()

app.MainLoop()

单击大 "Add" 按钮将添加新的 "foo" 按钮,但一旦到达框架底部就会停止。手动调整框架大小将使隐藏的第二列出现。

执行 Layout() 主面板的 sizer 而不是按钮面板的 sizer。

作为按钮面板的 sizer "lives" 在主面板的 sizer 中,这是需要重新计算的,因为它将重新计算它的子项。

def OnAddButton(self, evt):
    self.buttons_panel.add_button()
    #self.buttons_panel.Layout()
    self.Layout()

编辑:
对于更复杂的设置,您可能需要注意 parentgrandparent 并从按钮面板内更新,即

import wx

start_buttons = 5

class ButtonsPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.SetSizer(wx.WrapSizer(wx.VERTICAL))
        self.parent = parent
        for i in range(start_buttons):
            self.add_button()

    def add_button(self):
        self.GetSizer().Add(wx.Button(self, label='foo'),
                            wx.SizerFlags().Expand())
        self.parent.Layout()

class MyPanel(wx.Panel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # hardcoded size for sake of example only
        add_button = wx.Button(self, label="add", size=(80, 250))
        add_button.Bind(wx.EVT_BUTTON, self.OnAddButton)

        self.buttons_panel = ButtonsPanel(self)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(add_button)
        sizer.Add(self.buttons_panel, wx.SizerFlags().Expand())
        self.SetSizer(sizer)

    def OnAddButton(self, evt):
        self.buttons_panel.add_button()
        #self.buttons_panel.Layout()

class MyFrame(wx.Frame):
    def __init__(self, *args):
        super().__init__(*args)
        panel = MyPanel(self)


app = wx.App()
frame = MyFrame(None)
frame.Show()

app.MainLoop()

如果真的很糟糕,您可以使用 pubsub 在正确的位置发射 Layout