2
votes

I have a wxpython listctrl , which contains 4 column[A, B, C, D]. User selects any one of the row from listctrl. Now i have a button in my gui so when i click that i want to print the value of column D from that selected row. For example lets user has selected this row:
[PYTHON, JAVA, MATLAB, RUBY]
now if user clicks the button it should give output: RUBY
I am binding THE BUTTON in this way

self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnPlot, self.list) 

self.list.Append((j[0],j[1],j[2],j[3]))     #values are inserted in the listctrl 

And OnPlot event i have defined as: def OnPlot(self, event): click = event.GetText()

It doesn't work but. How can i accomplish this?

2

2 Answers

3
votes

The event will pass the index of the selected item from the listctrl.
Use the index to get the item and column within the listctrl, in this case 3.
Get the text of the column.
Namely:

def on_plot(self, event):
    ind = event.GetIndex()
    item = self.list_ctrl.GetItem(ind,3)
    print item.GetText()

This assumes that you have bound the listctrl like this:

self.list_ctrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_plot, self.list_ctrl)

Edit:
With regard to your comment and the edit to the title of the question. You cannot bind an arbitrary event to something. A button has a set of defined events as does a listctrl and never the twain shall meet. The way around your issue is to bind the button to a button event.

plot_button.Bind(wx.EVT_BUTTON, self.on_plot)

then define on_plot like this:

def on_plot(self, event):
    ind = self.list_ctrl.GetFirstSelected()
    if ind >=0:
        item = self.list_ctrl.GetItem(ind,3)
        print item.GetText()

As you will see it achieves the same end result but and it's a big but, you have already had to click on the listctrl to select an item. That being the case, you could have already achieved the same result, using the first method, without having to define the button in the first place and using this method you now have to check in case nothing was selected (ind must not be -1).

0
votes

The list control is kind of hard to work with in my opinion. Basically you will need to get what row you are on and hard code what column you are interested in. Something like this should get you started:

import wx


class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "List Control Tutorial")

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        self.index = 0
        self.current_selection = None

        self.list_ctrl = wx.ListCtrl(panel, size=(-1,100),
                                     style=wx.LC_REPORT
                         |wx.BORDER_SUNKEN
                         )
        self.list_ctrl.InsertColumn(0, 'Subject')
        self.list_ctrl.InsertColumn(1, 'Due')
        self.list_ctrl.InsertColumn(2, 'Location', width=125)
        self.list_ctrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_item_selected)

        btn = wx.Button(panel, label="Add Line")
        btn.Bind(wx.EVT_BUTTON, self.add_line)

        data_getter_btn = wx.Button(panel, label='Get all data')
        data_getter_btn.Bind(wx.EVT_BUTTON, self.on_get_data)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
        sizer.Add(data_getter_btn, 0, wx.ALL|wx.CENTER, 5)
        panel.SetSizer(sizer)

    def add_line(self, event):
        line = "Line %s" % self.index
        self.list_ctrl.InsertStringItem(self.index, line)
        self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
        self.list_ctrl.SetStringItem(self.index, 2, "USA")
        self.index += 1

    def on_item_selected(self, event):
        self.current_selection = event.m_itemIndex

    def on_get_data(self, event):
        if self.current_selection:
            print self.current_selection
            item = self.list_ctrl.GetItem(itemId=self.current_selection, col=2)
            print item.GetText()

#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()

The code above will print out the current selection (row number) and the 3rd column's text. If you want to print out all the rows and column's text, then you can do something like this:

import wx

########################################################################
class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "List Control Tutorial")

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        self.index = 0

        self.list_ctrl = wx.ListCtrl(panel, size=(-1,100),
                         style=wx.LC_REPORT
                         |wx.BORDER_SUNKEN
                         )
        self.list_ctrl.InsertColumn(0, 'Subject')
        self.list_ctrl.InsertColumn(1, 'Due')
        self.list_ctrl.InsertColumn(2, 'Location', width=125)

        btn = wx.Button(panel, label="Add Line")
        btn2 = wx.Button(panel, label="Get Data")
        btn.Bind(wx.EVT_BUTTON, self.add_line)
        btn2.Bind(wx.EVT_BUTTON, self.get_data)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
        sizer.Add(btn2, 0, wx.ALL|wx.CENTER, 5)
        panel.SetSizer(sizer)

    #----------------------------------------------------------------------
    def add_line(self, event):
        line = "Line %s" % self.index
        self.list_ctrl.InsertStringItem(self.index, line)
        self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
        self.list_ctrl.SetStringItem(self.index, 2, "USA")
        self.index += 1

    #----------------------------------------------------------------------
    def get_data(self, event):
        """"""
        count = self.list_ctrl.GetItemCount()
        cols = self.list_ctrl.GetColumnCount()
        for row in range(count):
            for col in range(cols):
                item = self.list_ctrl.GetItem(itemId=row, col=col)
                print item.GetText()

#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()

An easier way to accomplish this sort of thing though would be to associate objects with each row. Here's an example:

import wx

########################################################################
class Car(object):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, make, model, year, color="Blue"):
        """Constructor"""
        self.make = make
        self.model = model
        self.year = year
        self.color = color


########################################################################
class MyPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)

        rows = [Car("Ford", "Taurus", "1996"),
                Car("Nissan", "370Z", "2010"),
                Car("Porche", "911", "2009", "Red")
                ]

        self.list_ctrl = wx.ListCtrl(self, size=(-1,100),
                                style=wx.LC_REPORT
                                |wx.BORDER_SUNKEN
                                )
        self.list_ctrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onItemSelected)
        self.list_ctrl.InsertColumn(0, "Make")
        self.list_ctrl.InsertColumn(1, "Model")
        self.list_ctrl.InsertColumn(2, "Year")
        self.list_ctrl.InsertColumn(3, "Color")

        index = 0
        self.myRowDict = {}
        for row in rows:
            self.list_ctrl.InsertStringItem(index, row.make)
            self.list_ctrl.SetStringItem(index, 1, row.model)
            self.list_ctrl.SetStringItem(index, 2, row.year)
            self.list_ctrl.SetStringItem(index, 3, row.color)
            self.myRowDict[index] = row
            index += 1

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
        self.SetSizer(sizer)

    #----------------------------------------------------------------------
    def onItemSelected(self, event):
        """"""
        currentItem = event.m_itemIndex
        car = self.myRowDict[currentItem]
        print car.make
        print car.model
        print car.color
        print car.year

########################################################################
class MyFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, wx.ID_ANY, "List Control Tutorial")
        panel = MyPanel(self)
        self.Show()

#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

Quite frankly, I don't really use the ListCtrl much any more. I prefer using ObjectListView as it just seems easier to use and provides a lot more functionality out of the box. Here are a couple of links: