wxWidgets / Phoenix

wxPython's Project Phoenix. A new implementation of wxPython, better, stronger, faster than he was before.
http://wxpython.org/
2.33k stars 515 forks source link

PropertyGridManager event binding not working properly #2596

Open GodLike3539 opened 2 months ago

GodLike3539 commented 2 months ago

When binding an EVT_PG_CHANGED from a PropertyGridManager the event only gets handled when using PropertyGridManager.Bind() but not with Bind(..., MyPropertyGridManager).

The EVT_PG_CHANGED is an instance of wx.CommandEvent, so it should work with both ways.

Windows 11 Pro wx.version(): 4.2.1 msw (phoenix) wxWidgets 3.2.2.1, installed with pip install wxpython Python 3.12.4, stock

Description of the problem:

Code Example (click to expand) ```python import wx import wx.propgrid as pg class MyFrame(wx.Frame): def __init__(self, *args, **kw): super(MyFrame, self).__init__(*args, **kw) panel = wx.Panel(self) sizer = wx.BoxSizer(wx.VERTICAL) self.m_pg = pg.PropertyGridManager(panel, style=pg.PGMAN_DEFAULT_STYLE) self.page = pg.PropertyGridPage() self.page.Append(pg.IntProperty("an integer", "another_parameter", 123)) self.m_pg.AddPage("some page", wx.BitmapBundle(), self.page) # THIS DOES NOT WORK #self.Bind(pg.EVT_PG_CHANGED, self._on_event, self.m_pg) # THIS DOES self.m_pg.Bind(pg.EVT_PG_CHANGED, self._on_event) sizer.Add(self.m_pg, 1, wx.EXPAND | wx.ALL, 10) panel.SetSizer(sizer) self.SetSize((400, 300)) self.Centre() def _on_event(self, event): print('Property changed') print(isinstance(event, wx.CommandEvent)) class MyApp(wx.App): def OnInit(self): frame = MyFrame(None, title="pg event weirdness") frame.Show(True) return True app = MyApp(False) app.MainLoop() ```
reticulatus commented 2 months ago

This issue also occurs using wxPython 4.2.1 gtk3 (phoenix) wxWidgets 3.2.4 + Python 3.12.3 + Linux Mint 22.

I have noticed that in the case where the EVT_PG_CHANGED event handler does get called in your example, _event.ShouldPropagate() returns False.

That is different to some other event types derived from wx.CommandEvent. For example, when EVT_BUTTON and EVT_TEXT_ENTER are bound in an equivalent manner, their event object's ShouldPropagate() method returns True.

reticulatus commented 2 months ago

If you derive a new class from PropertyGridPage and override its IsHandlingAllEvents() method to return False:

class MyPropertyGridPage(pg.PropertyGridPage):
    def IsHandlingAllEvents(self):
        return False

and use it in your example instead of pg.PropertyGridPage() then the self.Bind(pg.EVT_PG_CHANGED, self._on_event, self.m_pg) binding does work.

I think because the base class PropertyGridPage.IsHandlingAllEvents() method returns True, the C++ code calls event.StopPropagation() to stop the event propagating to the parent.