当我将 size_event 绑定到处理程序函数时,为什么 wxPython 中的 sizer 不起作用?

Why sizer in wxPython not work when I bind size_event to a handler function?

import wx


class MyFrame(wx.Frame):
    def __init__(self, parent):
        self.parent = parent
        super(MyFrame, self).__init__(parent, -1, 'Test')

        # create a base panel
        self.panel = wx.Panel(self)
        self.panel.SetBackgroundColour('blue')
        vbox = wx.BoxSizer(wx.VERTICAL)

        # create a sub-panel 1.
        self.panel_1 = wx.Panel(self.panel, -1)
        self.panel_1.SetBackgroundColour('yellow')
        vbox.Add(self.panel_1, 1, wx.EXPAND)

        # create a sub-panel 2.
        self.panel_2 = wx.Panel(self.panel, -1)
        self.panel_2.SetBackgroundColour('pink')
        vbox.Add(self.panel_2, 1, wx.EXPAND)

        # This line of code cause the problem!
        self.panel.Bind(wx.EVT_SIZE, self._on_paint)

        self.panel.SetSizer(vbox)

        self.Show()

    def _on_paint(self, e):
        pass


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

上面的脚本不会产生理想的输出,其中两个子面板的大小应该相等并且一起占据所有帧。

理想的输出可以通过删除获得:

self.panel.Bind(wx.EVT_SIZE, self._on_paint)

我还测试过,如果脚本是 wx.EVT_PAINT 而不是 wx.EVT_SIZE,脚本是否可以正常工作。

那么,为什么上面的行会导致 sizer 无法正常工作?

因为基础 class 中的默认 EVT_SIZE 处理程序是执行使用 sizer 的自动布局的地方。通过使用您自己的处理程序拦截 EVT_SIZE 事件,您可以阻止该默认功能。

您可以在您的处理程序中调用 e.Skip(),这样事件处理系统将在您的处理程序完成后继续寻找匹配的事件处理程序,或者您可以将如下代码添加到您的处理程序中,这样布局算法将仍在执行:

  window = e.GetEventObject()
  if window.GetAutoLayout():
      window.Layout()