Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PropertyGridManager event binding not working properly #2596

Open
GodLike3539 opened this issue Sep 4, 2024 · 3 comments
Open

PropertyGridManager event binding not working properly #2596

GodLike3539 opened this issue Sep 4, 2024 · 3 comments

Comments

@GodLike3539
Copy link

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)
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()
@ghost
Copy link

ghost commented Sep 8, 2024

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.

@ghost
Copy link

ghost commented Sep 8, 2024

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.

@da-dada
Copy link

da-dada commented Mar 7, 2025

@GodLike3539 or subclass your property

import wx
import wx.propgrid as pg

class MyProperty(pg.IntProperty):
    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)

    def StringToValue(self, st, flags):
        """
        Convert a string to the correct type for the property.

        If failed, return False or (False, None). If success, return tuple
        (True, newValue).
        """
        print(f'stv {st} {flags} type of st {type(st)}')
        try:
            val = int(st)
            return (True, val)
        except (ValueError, TypeError):
            pass
        except:
            raise
        return (False, None)

class MyFrame(wx.Frame):
    def __init__(self, *args, **kw):
        super().__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(MyProperty("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()```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants