Recently I was trying to figure out how to add tooltips to each item in an ObjectListView widget in wxPython on Windows. The wxPython wiki has an example that uses PyWin32, but I didn’t want to go that route. So I asked on the wxPython Google Group and got an interesting answer. They had actually used one of my old articles to build their solution for me. I have cleaned it up a little bit and decided it was worth sharing with my readers:
import wx from ObjectListView import ObjectListView, ColumnDefn ######################################################################## class Book(object): """ Model of the Book object Contains the following attributes: 'ISBN', 'Author', 'Manufacturer', 'Title' """ #---------------------------------------------------------------------- def __init__(self, title, author, isbn, mfg): self.isbn = isbn self.author = author self.mfg = mfg self.title = title ######################################################################## class MainPanel(wx.Panel): #---------------------------------------------------------------------- def __init__(self, parent): wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY) self.products = [Book("wxPython in Action", "Robin Dunn", "1932394621", "Manning"), Book("Hello World", "Warren and Carter Sande", "1933988495", "Manning") ] self.dataOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER) self.setBooks() # Allow the cell values to be edited when double-clicked self.dataOlv.cellEditMode = ObjectListView.CELLEDIT_SINGLECLICK # create an update button updateBtn = wx.Button(self, wx.ID_ANY, "Update OLV") updateBtn.Bind(wx.EVT_BUTTON, self.updateControl) # Create some sizers mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(self.dataOlv, 1, wx.ALL|wx.EXPAND, 5) mainSizer.Add(updateBtn, 0, wx.ALL|wx.CENTER, 5) self.SetSizer(mainSizer) self.dataOlv.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onSetToolTip) #---------------------------------------------------------------------- def updateControl(self, event): """ Update the control """ print "updating..." #product_dict = [{"title":"Core Python Programming", "author":"Wesley Chun", #"isbn":"0132269937", "mfg":"Prentice Hall"}, #{"title":"Python Programming for the Absolute Beginner", #"author":"Michael Dawson", "isbn":"1598631128", #"mfg":"Course Technology"}, #{"title":"Learning Python", "author":"Mark Lutz", #"isbn":"0596513984", "mfg":"O'Reilly"} #] product_list = [Book("Core Python Programming", "Wesley Chun", "0132269937", "Prentice Hall"), Book("Python Programming for the Absolute Beginner", "Michael Dawson", "1598631128", "Course Technology"), Book("Learning Python", "Mark Lutz", "0596513984", "O'Reilly") ] data = self.products + product_list self.dataOlv.SetObjects(data) #---------------------------------------------------------------------- def setBooks(self, data=None): """ Sets the book data for the OLV object """ self.dataOlv.SetColumns([ ColumnDefn("Title", "left", 220, "title"), ColumnDefn("Author", "left", 200, "author"), ColumnDefn("ISBN", "right", 100, "isbn"), ColumnDefn("Mfg", "left", 180, "mfg") ]) self.dataOlv.SetObjects(self.products) #---------------------------------------------------------------------- def onSetToolTip(self, event): """ Set the tool tip on the selected row """ item = self.dataOlv.GetSelectedObject() tooltip = "%s is a good writer!" % item.author event.GetEventObject().SetToolTipString(tooltip) event.Skip() ######################################################################## class MainFrame(wx.Frame): #---------------------------------------------------------------------- def __init__(self): wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title="ObjectListView Demo", size=(800,600)) panel = MainPanel(self) ######################################################################## class GenApp(wx.App): #---------------------------------------------------------------------- def __init__(self, redirect=False, filename=None): wx.App.__init__(self, redirect, filename) #---------------------------------------------------------------------- def OnInit(self): # create frame here frame = MainFrame() frame.Show() return True #---------------------------------------------------------------------- def main(): """ Run the demo """ app = GenApp() app.MainLoop() if __name__ == "__main__": main()
All I needed to do was add a binding to wx.EVT_LIST_ITEM_SELECTED. Then in my event handler I needed to grab the event object and set its tooltip string. What I would really like to do is find a way to copy this grid recipe so that I can just mouse over items and have the tooltip change, but it doesn’t look like ObjectListView / ListCtrl has the methods I would need to translate mouse coordinates to a column / row. Regardless, the solution given does work as advertised. Thanks a lot, Erxin!
Update: One of my astute readers noticed an error in my code where when I hit the update button, it added a dictionary to the ObjectListView widget. While you can add a dictionary, this broke the onSetToolTip method as some of the items that were added were no longer Book instances. So I have updated the code to add the extra items as Book instances and commented out the dictionary example.
The post wxPython: Adding Tooltips to ObjectListView appeared first on The Mouse Vs. The Python.