Search code examples
wxpython

Mouse position of PropertyGrid event


I would like to implement a context/popup menu for a PropertyGrid and offer property-specific commands, e.g. "Export item". The menu would pop up when clicking on the name-field. I do not intend to change the popup menu that is readily provided for the value-field, e.g. Copy&Paste functionality.

PropertyGrid offers an event wx.propgrid.EVT_PG_RIGHT_CLICK. This lets me extract the PGProperty information (name/value) using

def OnRightClick(event):
    selectedName = event.GetProperty().GetName()
    selectedValue = event.GetProperty().GetValue()

However, this does not offer any location of the mouse event as wx.MouseEvent would:

self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)  
def OnRightDown(event):
    self.PopupMenu(self, event.GetPosition())

How can I determine the X/Y-location to open a popup menu on the name-field of a PropertyGrid?

The menu is essentially defined as

class PopMenu(wx.Menu):
    def __init__(self, parent):
        super(PopMenu, self).__init__()
        self.parent = parent
        popmenu = wx.MenuItem(self, wx.NewId(), 'item')
        self.Append(popmenu)

Solution

  • There doesn't appear to be a direct method of getting this information, so you'll have to improvise.
    Try using a combination of wx.GetMousePosition and then use the windows ScreenToClient function, if you need the position relative to the window.

    import wx
    import wx.propgrid as wxpg
    import datetime
    
    class TestPanel(wx.Panel):
        def __init__(self,parent):
            wx.Panel.__init__(self,parent)
            self.SetSizer(wx.BoxSizer(wx.VERTICAL))
            self.pg = wxpg.PropertyGridManager(self,
                        style=wxpg.PG_SPLITTER_AUTO_CENTER |
                              wxpg.PG_TOOLBAR)
    
            # Show help as tooltips
            mychoices = ["1","2","3","4","5"]
            self.pg.SetExtraStyle(wxpg.PG_EX_HELP_AS_TOOLTIPS)
            self.pg.Append(wxpg.IntProperty("Number"))
            self.pg.Append(wxpg.StringProperty("Word", value="Some text"))
            self.pg.Append(wxpg.BoolProperty("Boolean"))
            self.pg.Append(wxpg.ColourProperty("Colour"))
            self.pg.Append(wxpg.MultiChoiceProperty("Choose","Choose",mychoices,value=["1"]))
            now_date = wx.DateTime.Now()
            self.pg.Append( wxpg.DateProperty("Date",value=now_date))
            self.pg.Bind(wxpg.EVT_PG_RIGHT_CLICK, self.OnRightClick)
            self.GetSizer().Add(self.pg,proportion=1,flag=wx.EXPAND)
    
            #define popup menu
            self.popupmenu = wx.Menu()
            self.top = wx.MenuItem(self.popupmenu, wx.ID_ANY, "Title")
            self.popupmenu.Append(self.top)
            self.popupmenu.AppendSeparator()        
            for text in "one two three four five".split():
                item = self.popupmenu.Append(-1, text)
    
        def OnRightClick(self, event):
            scr = wx.GetMousePosition()
            rel = self.ScreenToClient(scr)
            #print("screen Pos", scr, "Client", rel)
            #open popup menu at right click location - identifying the item clicked
            self.popupmenu.Delete(self.top)
            self.top = wx.MenuItem(self.popupmenu, wx.ID_ANY, event.GetProperty().GetName())
            self.popupmenu.Prepend(self.top)
            self.PopupMenu(self.popupmenu, rel)
    
    class wxFrame(wx.Frame):
        def __init__(self, parent, title):
            wx.Frame.__init__(self, parent, title=title)
            self.panel = TestPanel(self)
            self.Show(True)
    
    if __name__ == "__main__":
        app = wx.App(False)
        frame = wxFrame(None, 'Property Grid Test')
        app.MainLoop()
    

    enter image description here