One of the new agw widgets to be included in wxPython is one called the UltimateListCtrl. It’s a pure Python widget that can have pretty much any other widget stuck into any of the cells, which makes it really flexible. It also allows the skilled programmer the ability to add custom renderers to make the interface different. In this article, we will take a quick look at this fascinating widget.

Getting Started

The simplest way to learn a new widget is to look at an example. You can look at the wxPython demo for the 2.9 series if you want to see several complex demos of this awesome widget, but for our purposes, we’re going to create a stripped down version that’s based on one of those demos, namely the report view version. Here’s the code for your viewing pleasure:

import wx from wx.lib.agw import ultimatelistctrl as ULC ######################################################################## class TestPanel(wx.Panel): """""" #---------------------------------------------------------------------- def __init__(self, parent): """Constructor""" wx.Panel.__init__(self, parent) try: font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) boldfont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) except AttributeError: # wxPython 4 / Phoenix updated SystemSettings font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) boldfont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) boldfont.SetWeight(wx.BOLD) boldfont.SetPointSize(12) self.ultimateList = ULC.UltimateListCtrl(self, agwStyle = wx.LC_REPORT | wx.LC_VRULES | wx.LC_HRULES) info = ULC.UltimateListItem() info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK info._image = [] info._format = 0 info._kind = 1 info._text = "Artist Name" self.ultimateList.InsertColumnInfo(0, info) info = ULC.UltimateListItem() info._format = wx.LIST_FORMAT_RIGHT info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_FONT info._image = [] info._text = "Title" info._font = boldfont self.ultimateList.InsertColumnInfo(1, info) info = ULC.UltimateListItem() info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT info._format = 0 info._text = "Genre" info._font = font info._image = [] self.ultimateList.InsertColumnInfo(2, info) self.ultimateList.InsertStringItem(0, "Newsboys") self.ultimateList.SetStringItem(0, 1, "Go") self.ultimateList.SetStringItem(0, 2, "Rock") self.ultimateList.InsertStringItem(1, "Puffy") self.ultimateList.SetStringItem(1, 1, "Bring It!") self.ultimateList.SetStringItem(1, 2, "Pop") self.ultimateList.InsertStringItem(2, "Family Force 5") self.ultimateList.SetStringItem(2, 1, "III") self.ultimateList.SetStringItem(2, 2, "Crunk") self.ultimateList.SetColumnWidth(0, 150) self.ultimateList.SetColumnWidth(1, 200) self.ultimateList.SetColumnWidth(2, 100) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.ultimateList, 1, wx.EXPAND) self.SetSizer(sizer) ######################################################################## class TestFrame(wx.Frame): """""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" wx.Frame.__init__(self, None, title="MvP UltimateListCtrl Demo") panel = TestPanel(self) self.Show() #---------------------------------------------------------------------- if __name__ == "__main__": app = wx.App(False) frame = TestFrame() app.MainLoop()

Let’s take a few moments to break this down a bit. First off, to import this widget, we need to do something like the following: from wx.lib.agw import ultimatelistctrl as ULC. Then to instantiate it, we call ULC.UltimateListCtrl() and pass it a few key values. In this case, we pass in a parent and three styles: wx.LC_REPORT, wx.LC_VRULES and wx.LC_HRULES. The first agwStyle is LC_REPORT, which puts the widget in “Report” mode, probably the most common mode you’ll see for a ListCtrl and one of the most useful. The other two styles put vertical and horizontal lines in, respectively.

Next, we want to create our columns. We use ULC.UltimateListItem to do that, although according to the documentation, this can also be used to create “items” too. As you can see, the UltimateListItem has many attributes that we can set. You can add an image, a checkbox (via the mask and the style: ULC.ULC_MASK_CHECK), a kind (0 – normal, 1 – checkbox, 2 – radio button), a format (which controls label positioning), the font and text and several others. Once you’ve set that stuff up, you call the UltimateListItem object’s InsertColumnInfo() method on it to apply your settings.

Finally, to add data to the UltimateListCtrl, we do the same thing that we would do with a normal ListCtrl. Namely, we first call InsertStringItem(index, label) where index is the row number. Then to add strings to the other columns, you’ll want to call SetStringItem(index, col, label). There are lots of other methods you can call to add other types of data, but you’ll need to read the demo’s source or the documentation to learn that. And now we’re done with our first demo!

Wrapping Up

There is a lot more information to be found in the official wxPython 2.9 series demo. In fact, there are several demos showing the various styles and UI variations that this widget can do. You can see an example of one of those demos in the screenshot at the beginning of this article. I would recommend this widget any time you need to insert other widgets into the cells of a ListCtrl or whenever you need lots of control over the widget’s presentation. Happy hacking!

Further Reading