How to create QListWidgetItem with aligned left and right text in Qt?
-
I'm trying to create a QListWidget where each QListWidgetItem displays text in two parts:
- Left-aligned text on the left side
- Right-aligned text on the right side
Example of desired layout:
I know I can add spaces between the left and right text, but this isn't reliable since:
- Font width can vary
- Widget width can change
- Text lengths are dynamic
What's the proper way to implement this kind of layout with QListWidget?
Btw, I'm using Qt 6.8 on Windows.
-
Using a custom QStyledItemDelegate like this
class CustomListWidgetItemDelegate : public QStyledItemDelegate { public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { painter->save(); if (option.state & QStyle::State_Selected) painter->fillRect(option.rect, option.palette.highlight()); else if (option.state & QStyle::State_MouseOver) painter->fillRect(option.rect, option.palette.highlight()); //left aligned if(index.data(Qt::DisplayRole).isValid()) { QString text = index.data(Qt::DisplayRole).toString(); painter->drawText(QPoint(option.rect.left() + 5, option.rect.bottom()-5), text); } //right aligned if(index.data(Qt::UserRole).isValid()) { QString text = index.data(Qt::UserRole).toString(); int textwidth = painter->fontMetrics().boundingRect(text).width(); painter->drawText(QPoint(option.rect.right() - textwidth - 5, option.rect.bottom()-5), text);; } //fixed if(index.data(Qt::UserRole + 1).isValid()) { QString text = index.data(Qt::UserRole + 1).toString(); painter->drawText(QPoint(200, option.rect.bottom()-5), text);; } painter->restore(); } };
Now that theres more than one text, the other texts are stored in UserRoles
//install delegate on the ListWidget ui->listWidget->setItemDelegate(new CustomListWidgetItemDelegate); QListWidgetItem * item = nullptr; for(int i = 0; i < 5; i++) { item = new QListWidgetItem("ListItem"); item->setData(Qt::UserRole, "Yep"); item->setData(Qt::UserRole + 1, "Maybe"); ui->listWidget->addItem(item); }
-
Use text Alignment. Did you get a chance to look at the doc here
https://doc.qt.io/qt-6/qlistwidgetitem.html#setTextAlignment -
@dheerendra How would you use that to place some text at left and some text at right?
-
Maybe you want to check how
QShortcut
is implemented forQAction
andQMenu
, because this is what you are showing there. -
@JonB Read the question on more time. My interpretation was wrong. Same widget align left/right. No direct way.
-
Using a custom QStyledItemDelegate like this
class CustomListWidgetItemDelegate : public QStyledItemDelegate { public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { painter->save(); if (option.state & QStyle::State_Selected) painter->fillRect(option.rect, option.palette.highlight()); else if (option.state & QStyle::State_MouseOver) painter->fillRect(option.rect, option.palette.highlight()); //left aligned if(index.data(Qt::DisplayRole).isValid()) { QString text = index.data(Qt::DisplayRole).toString(); painter->drawText(QPoint(option.rect.left() + 5, option.rect.bottom()-5), text); } //right aligned if(index.data(Qt::UserRole).isValid()) { QString text = index.data(Qt::UserRole).toString(); int textwidth = painter->fontMetrics().boundingRect(text).width(); painter->drawText(QPoint(option.rect.right() - textwidth - 5, option.rect.bottom()-5), text);; } //fixed if(index.data(Qt::UserRole + 1).isValid()) { QString text = index.data(Qt::UserRole + 1).toString(); painter->drawText(QPoint(200, option.rect.bottom()-5), text);; } painter->restore(); } };
Now that theres more than one text, the other texts are stored in UserRoles
//install delegate on the ListWidget ui->listWidget->setItemDelegate(new CustomListWidgetItemDelegate); QListWidgetItem * item = nullptr; for(int i = 0; i < 5; i++) { item = new QListWidgetItem("ListItem"); item->setData(Qt::UserRole, "Yep"); item->setData(Qt::UserRole + 1, "Maybe"); ui->listWidget->addItem(item); }
-