Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QListView/QListWidget with custom items and custom item widgets

I'm writing a PyQt application and am having some trouble creating a custom list view. I'd like the list to contain arbitrary widgets (one custom widget in particular). How would I go about this?

It seems that the alternative would be to create a table or grid view wrapped in a scrollbar. However, I'd like to be able to take advantage of the model/view approach as well as the nesting (tree-view) support the built-ins handle.

To clarify, the custom widgets are interactive (contain buttons), so the solution requires more than painting a widget.

like image 449
Daniel Naab Avatar asked Jun 04 '09 03:06

Daniel Naab


People also ask

How do I make QListWidget editable?

double-click the list-widget to show the Edit List Widget dialog. in the dialog, select an item and click the Properties button. scroll down to the bottom of the properties list. check the checkbox for the Editable flag.

What is QListWidget?

QListWidget is a convenience class that provides a list view similar to the one supplied by QListView , but with a classic item-based interface for adding and removing items. QListWidget uses an internal model to manage each QListWidgetItem in the list.

What is QListView?

A QListView presents items stored in a model, either as a simple non-hierarchical list, or as a collection of icons. This class is used to provide lists and icon views that were previously provided by the QListBox and QIconView classes, but using the more flexible approach provided by Qt's model/view architecture.


1 Answers

I think you need to subclass QItemDelegate.

QItemDelegate can be used to provide custom display features and editor widgets for item views based on QAbstractItemView subclasses. Using a delegate for this purpose allows the display and editing mechanisms to be customized and developed independently from the model and view.

This code is taken from Qt's examples, the torrent application.

class TorrentViewDelegate : public QItemDelegate {     Q_OBJECT public:     inline TorrentViewDelegate(MainWindow *mainWindow) : QItemDelegate(mainWindow) {}      inline void paint(QPainter *painter, const QStyleOptionViewItem &option,                       const QModelIndex &index ) const     {         if (index.column() != 2) {             QItemDelegate::paint(painter, option, index);             return;         }          // Set up a QStyleOptionProgressBar to precisely mimic the         // environment of a progress bar.         QStyleOptionProgressBar progressBarOption;         progressBarOption.state = QStyle::State_Enabled;         progressBarOption.direction = QApplication::layoutDirection();         progressBarOption.rect = option.rect;         progressBarOption.fontMetrics = QApplication::fontMetrics();         progressBarOption.minimum = 0;         progressBarOption.maximum = 100;         progressBarOption.textAlignment = Qt::AlignCenter;         progressBarOption.textVisible = true;          // Set the progress and text values of the style option.         int progress = qobject_cast<MainWindow *>(parent())->clientForRow(index.row())->progress();         progressBarOption.progress = progress < 0 ? 0 : progress;         progressBarOption.text = QString().sprintf("%d%%", progressBarOption.progress);          // Draw the progress bar onto the view.         QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);     } }; 

Basically as you can see it checks if the column to be painted is of a specific index, if so it paints a progress bar. I think you could tweak it a little and instead of using a QStyleOption you could use your own widget.

edit: don't forget to setup your item delegate with your QListView using setItemDelegate.

While investigating your question I've stumbled upon this thread, which elaborates how to paint a custom widget using a QItemDelegate, I believe it has all the info you might need.

like image 103
Idan K Avatar answered Sep 22 '22 23:09

Idan K