Search code examples
wxpythonobjectlistview-python

Is there a way to get the object selected in an object list view?


In my python application I have objects displayed in an object list view. I want to use a context menu to move the objects up and down the list.

Is there any way to identify the object that has been clicked on by the mouse right click (this is not necessarily the selected object)?

import wx
from ObjectListView import (ObjectListView, ColumnDefn)

class MainFrame(wx.Frame):
    MIN_SIZE = (500, 400)
    def __init__(self, *args, **kwargs):
        super(MainFrame, self).__init__(None, *args, **kwargs)
        self.panel = MainPanel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.panel)
        self.SetSizer(sizer)
        self.Center()
        self.SetMinSize(self.MIN_SIZE)
        self.Show()
        widgets = [Widget('a'), Widget('b'),Widget('c')]
        self.panel.olv_widgets.SetObjects(widgets)

    def on_olv_widgets_right_down(self,event):
        self.PopupMenu(UpDownMenu(self), event.GetPosition())
        print(event.GetPosition())

    def on_cell_select(self, event):
        print('on_cell_select')

    def move_item_down(self, event):
        print('move_item_down')

    def move_item_up(self, event):
        print('move_item_up')

class MainPanel(wx.Panel):
    LIST_SIZE = (2000, 2000)
    def __init__(self, parent, *args, **kwargs):
        super(MainPanel, self).__init__(parent, *args, **kwargs)

        self.olv_widgets = ObjectListView(self, wx.ID_ANY,
                                            style=wx.LC_REPORT|wx.SUNKEN_BORDER,
                                            size=self.LIST_SIZE)
        self.olv_widgets.SetColumns(
                [ColumnDefn('Widget', 'left', parent.MIN_SIZE[0],
                 'description', isSpaceFilling=True)])

        self.olv_widgets.Bind(wx.EVT_RIGHT_DOWN, parent.on_olv_widgets_right_down)
        self.olv_widgets.Bind(wx.EVT_LIST_ITEM_SELECTED, parent.on_cell_select)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.olv_widgets, proportion=1, flag=wx.EXPAND)
        self.SetSizer(sizer)
        sizer.Fit(self)


class UpDownMenu(wx.Menu):
    def __init__(self, parent):
        super(UpDownMenu, self).__init__()
        up_menu_item = wx.MenuItem(self, wx.NewId(), 'Move item up')
        self.Append(up_menu_item)
        self.Bind(wx.EVT_MENU, parent.move_item_up, up_menu_item)
        down_menu_item = wx.MenuItem(self, wx.NewId(), 'Move item down')
        self.Append(down_menu_item)
        self.Bind(wx.EVT_MENU, parent.move_item_down, down_menu_item)


class Widget(object):
    def __init__(self, description):
        self.description = description

if __name__ == '__main__':
    wx_app = wx.App()
    MainFrame()
    wx_app.MainLoop()

Solution

  • You need to bind the ObjectListView instance to wx.EVT_LIST_ITEM_RIGHT_CLICK. I rearranged your code a bit to make an example:

    import wx
    from ObjectListView import ObjectListView, ColumnDefn
    
    class MainFrame(wx.Frame):
        MIN_SIZE = (500, 400)
        def __init__(self, *args, **kwargs):
            super(MainFrame, self).__init__(None, *args, **kwargs)
            self.panel = MainPanel(self)
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.panel)
            self.SetSizer(sizer)
            self.Center()
            self.SetMinSize(self.MIN_SIZE)
            self.Show()
            widgets = [Widget('a'), Widget('b'),Widget('c')]
            self.panel.olv_widgets.SetObjects(widgets)
    
        def on_cell_select(self, event):
            print('on_cell_select')
    
    
    class MainPanel(wx.Panel):
        LIST_SIZE = (2000, 2000)
        def __init__(self, parent, *args, **kwargs):
            super(MainPanel, self).__init__(parent, *args, **kwargs)
    
            self.olv_widgets = ObjectListView(self, wx.ID_ANY,
                                                style=wx.LC_REPORT|wx.SUNKEN_BORDER,
                                                size=self.LIST_SIZE)
            self.olv_widgets.SetColumns(
                    [ColumnDefn('Widget', 'left', parent.MIN_SIZE[0],
                     'description', isSpaceFilling=True)])
            self.olv_widgets.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.on_right_click)
    
            self.olv_widgets.Bind(wx.EVT_LIST_ITEM_SELECTED, parent.on_cell_select)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.olv_widgets, proportion=1, flag=wx.EXPAND)
            self.SetSizer(sizer)
            sizer.Fit(self)
    
        def on_right_click(self,event):
            self.list_item_clicked = self.olv_widgets.GetSelectedObject()
            print(self.list_item_clicked.description)
            self.PopupMenu(UpDownMenu(self), self.olv_widgets.GetPosition())
    
        def move_item_down(self, event):
            print('move_item_down')
    
        def move_item_up(self, event):
            print('move_item_up')
    
    
    
    class UpDownMenu(wx.Menu):
        def __init__(self, parent):
            super(UpDownMenu, self).__init__()
            up_menu_item = wx.MenuItem(self, wx.NewId(), 'Move item up')
            self.Append(up_menu_item)
            self.Bind(wx.EVT_MENU, parent.move_item_up, up_menu_item)
            down_menu_item = wx.MenuItem(self, wx.NewId(), 'Move item down')
            self.Append(down_menu_item)
            self.Bind(wx.EVT_MENU, parent.move_item_down, down_menu_item)
    
    
    class Widget(object):
        def __init__(self, description):
            self.description = description
    
    if __name__ == '__main__':
        wx_app = wx.App()
        MainFrame()
        wx_app.MainLoop()