This article is part 6 of 8 in the series Python PySide/PyQt Tutorial
Last Updated: Thursday 12th December 2013

Qt has a couple of widgets that allow single-column list selector controls — for brevity and convenience, we'll call them list boxes. The most flexible way is to use a QListView, which provides a UI view on a highly-flexible list model which must be defined by the programmer; a simpler way is to use a QListWidget, which has a pre-defined item-based model that allows it to handle common use-cases for a list box. We'll start with the simpler QListWidget.

The QListWidget

The constructor of a QListWidget is like that of many QWidget-descended objects, and takes only an optional parent argument:

Filling a QListWidget

Filling a QListWidget with items is easy. If your items are plain text, you can add them singly:

Or in bulk:

You can also add slightly more complicated list items using the QListWidgetItem class. A QListWidgetItem can be created in isolation and added to a list later using the list's addItem method:

More complex QListWidget items

Or it can be created with the list as a parent, in which case it is automatically added to the list:

An item can have text set via its setText method:

And an icon set to an instance of QIcon using its setIcon method:

You can also specify the text or an icon and text in the QListWidgetItem's constructor:

Each of the above constructor signatures may optionally accept a parent as well.

Using a QListWidget

The QListWidget offers several convenient signals that you can use to respond to user input. The most important is the currentItemChanged signal, which is emitted when the user changes the selected item; its slots receive two arguments, current and previous, which are the currently and previously selected QListWidgetItems. There are also signals for when a user clicks, double-clicks, activates, or presses an item, and when the set of selected items is changed.

To get the currently selected item, you can either use the arguments passed by the currentItemChanged signal or you can use the QListWidget's currentItem method.

A Note On QIcons

One of the few ways you can customize a QListWidgetItem is by adding an icon, so it is important that you gain some understanding of QIcons. There are many ways of constructing a QIcon; you can create them by:

  • Providing a filename: icon = QIcon('/some/path/to/icon.png').
  • Using a theme icon: icon = QIcon.fromTheme('document-open').
  • From a QPixMap: icon = QIcon(some_pixmap).

And many others. A couple comments on the different methods: first, note that the file-based creation supports a wide but not unlimited set of file types; you can find out which are supported by your version and platform by running QImageReader().supportedImageFormats(). On my system, it returns:

As I said, a pretty wide selection. Theme-based icon creation is problematic outside of well-established platforms; on Windows and OS X you should be fine, as well as if you're on Linux using Gnome or KDE, but if you use a less common desktop environment, such as OpenBox or XFCE, Qt might not be able to find your icons; there are ways around that, but no good ones, so you may be stuck with text only.

A QListWidget Example

Let's create a simple list widget that displays the file-name and a thumbnail icon for all the images in a directory. Since the items are simple enough to create as a QListWidgetItem, we'll have it inherit from QListWidget.

First off, we'll need to know what image formats are supported by your installation, so our list control can tell what's a valid image. We can use the method mentioned above, QImageReader().supportedImageFormats(). We'll convert them all to strings before we return them:

Now that we have that, we can build our image-list widget; we'll call it - intuitively enough - ImageFileWidget. It will inherit from QListWidget, and in addition to an optional parent argument, like all QWidgets, it will take a required dirpath:

We'll want it to have a way to determine what images are in a given directory. We'll give it an _images method that will return the file-names of all valid images in the specified directory. It'll employ the glob module's glob function, which does shell-style pattern-matching of file and directory paths:

Now that we have a way of figuring out what image files are in the directory, it's a simple matter to add them to our QListWidget. For each file-name, we create a QListWidgetItem with the list as its parent, set its text to the file-name, and set its icon to a QIcon created from the file:

Finally, we'll add a method to set the directory path that repopulates the list every time it is called:

And we'll add a line to the constructor to call the setDirpath method:

This, then, is our final code for our ImageFileList class:

So let's put our ImageFileList in a simple window so we can see it in action. We'll create a QWidget to serve as our window, stick a QVBoxLayout in it, and add the ImageFileList, along with an entry widget that will display the currently selected item. We'll use the ImageFileList's currentItemChanged signal to keep them synchronized.

We'll create a QApplication object, passing it an empty list so we can use sys.argv[1] to pass in the image directory:

Then, we'll create our window, setting a minimum size and adding a layout:

Then, we'll instantiate an ImageFileList, passing in the received image directory path and our window as its parent:

And add our entry widget:

And add both widgets to our layout:

Then, we need to create a slot function to be called when the current item is changed; it has to take arguments, curr and prev, the currently and previously selected items, and should set the entry's text to the text of the current item:

Then, we'll hook it up to the signal:

All that's left is to show the window and run the app:

Our final section, wrapped in the standard if __name__ == '__main__' block, then, is:

Running our whole example requires that you have a directory full of images; I used one in my Linux distribution's /usr/share/icons directory as an example:

But you will have to find your own. Almost any images will do.

The QListWidget is obviously a very simple widget, and doesn't offer many options; there are a lot of use cases for which it will not suffice. For those cases, you will probably use a QListView, which we will discuss in the next installment.

About The Author