It’s a little difficult to suggest a “better” solution without seeing exactly how your list item looks, but we will try it.
Actually there is a great post in the Qt thread which finally at the end gives all the code that they use to create the list like the one they show at the top.
In principle, each element has a large icon, and on the right is the title and description text, each of which differs in different ways.
Creating a custom delegate sounds intimidating, but it's basically a simple custom list widget. It works essentially like a template. You determine how you want your list item to look, and you draw it using the data from the list. You can simply inherit from QAbstractItemDelegate.
#include <QPainter> #include <QAbstractItemDelegate> class ListDelegate : public QAbstractItemDelegate { public: ListDelegate(QObject *parent = 0); void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; virtual ~ListDelegate(); };
The biggest challenge is to encode the drawing function. I will just show the basic information, but you can link to the link above for a longer example.
ListDelegate::ListDelegate(QObject *parent) : QAbstractItemDelegate(parent) { } void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { QRect r = option.rect; QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); if(option.state & QStyle::State_Selected) { painter->setBrush(Qt::cyan); painter->drawRect(r); } else { //BACKGROUND ALTERNATING COLORS painter->setBrush( (index.row() % 2) ? Qt::white : QColor(252,252,252) ); painter->drawRect(r); } painter->setPen(fontPen); //GET TITLE, DESCRIPTION AND ICON QIcon ic = QIcon(qvariant_cast<QPixmap>(index.data(Qt::DecorationRole))); QString title = index.data(Qt::DisplayRole).toString(); QString description = index.data(Qt::UserRole).toString(); int imageSpace = 10; if (!ic.isNull()) { //ICON r = option.rect.adjusted(5, 10, -10, -10); ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); imageSpace = 55; } //TITLE r = option.rect.adjusted(imageSpace, 0, -10, -30); painter->setFont( QFont( "Lucida Grande", 6, QFont::Normal ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, title, &r); //DESCRIPTION r = option.rect.adjusted(imageSpace, 30, -10, 0); painter->setFont( QFont( "Lucida Grande", 5, QFont::Normal ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, description, &r); } QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const { return QSize(200, 60); // very dumb value } ListDelegate::~ListDelegate() { }
So, you can see in this code that we get three bits of data from the list. Icon, title and description. Then we show the icon icon and draw two text lines as we like. But the important part is getting the data itself. We basically ask the list to provide us with data using the “index” that was passed to us.
QIcon ic = QIcon(qvariant_cast<QPixmap>(index.data(Qt::DecorationRole))); QString title = index.data(Qt::DisplayRole).toString(); QString description = index.data(Qt::UserRole + 1).toString();
You will notice that each bit of information was obtained using a different "role". Usually, only one thing is displayed in the list, accessed through DisplayRole. Icons are stored in the scenery. But if you want to store more things, then you start using UserRole. You can store a whole bunch of things using UserRole, UserRole +1, UserRole +2, etc.
So, how do you store all this information in each element. Easy...
QListWidgetItem *item = new QListWidgetItem(); item->setData(Qt::DisplayRole, "Title"); item->setData(Qt::UserRole, "Description"); myListWidget->addItem(item);
And finally, how can you display a list using your new delegate?
myListWidget->setItemDelegate(new ListDelegate(myListWidget));
I hope this clarified the situation a bit.