Overlaying text on top of QIcon in QListWidget in Pyside2
-
Either you write your own delegate inherit from QItemDelegate & return custom QWidget.
OR
Just your custom widget and set the custom Widget using setItemWidget(...) .2nd Option seems to easy one.
@dheerendra said in Overlaying text on top of QIcon in QListWidget in Pyside2:
Just your custom widget and set the custom Widget using setItemWidget(...) .
2nd Option seems to easy one.
Where's @VRonin...?
-
Hi,
There's no need at all for setItemWidget nor a custom widget from a QItemDelegate. A subclass of QStyledItemDelegate with its paint event re-implemented is enough.
-
Sorry but I'll use C++ as I don't know python
class TextOverDelegate : public QStyledItemDelegate{ Q_OBJECT Q_DISABLE_COPY(TextOverDelegate) public: explicit TextOverDelegate(QObject* parent = Q_NULLPTR) :QStyledItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE{ QStyledItemDelegate::paint(painter,option,index); const QVariant text = index.data(Qt::UserRole); if(text.isValid()){ const QStyle *style = option.widget ? option.widget->style() : QApplication::style(); style->drawItemText(painter, option.rect, Qt::AlignCenter, option.palette, option.state & QStyle::State_Enabled, text.toString()); } } };
This delegate will paint the text stored using
QListWidgetItem::setData
passingQt::UserRole
-
Sorry but I'll use C++ as I don't know python
class TextOverDelegate : public QStyledItemDelegate{ Q_OBJECT Q_DISABLE_COPY(TextOverDelegate) public: explicit TextOverDelegate(QObject* parent = Q_NULLPTR) :QStyledItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE{ QStyledItemDelegate::paint(painter,option,index); const QVariant text = index.data(Qt::UserRole); if(text.isValid()){ const QStyle *style = option.widget ? option.widget->style() : QApplication::style(); style->drawItemText(painter, option.rect, Qt::AlignCenter, option.palette, option.state & QStyle::State_Enabled, text.toString()); } } };
This delegate will paint the text stored using
QListWidgetItem::setData
passingQt::UserRole
Thanks a bunch for the detailed response! I tried implementing the sublclass of QStyledItemDelegate in Pyside2, however I'm getting
AttributeError: 'PySide2.QtWidgets.QListWidget' object has no attribute 'drawItemText'
I understand you are not super familiar with Python, but might you or somebody else who is be able to identify what I did wrong? Thank you!My Pyside 2 implementation:
class TextOverDelegate(QStyledItemDelegate): def __init__(self, parent=None): super(TextOverDelegate, self).__init__(parent) def paint(self, painter, option, index): text = index.data(QtCore.Qt.UserRole) if(option.widget): style = option.widget else: style = QApplication.style() style.drawItemText(painter, option.rect,QtCore.Qt.AlignCenter, option.palette, option.state & QStyle.State_Enabled, text)
In the main UI window class all I set the new delegate as the list widget's current item delegate.
self.custom_delegate = TextOverDelegate() self.listWidget.setItemDelegate(self.custom_delegate)
-
Thanks a bunch for the detailed response! I tried implementing the sublclass of QStyledItemDelegate in Pyside2, however I'm getting
AttributeError: 'PySide2.QtWidgets.QListWidget' object has no attribute 'drawItemText'
I understand you are not super familiar with Python, but might you or somebody else who is be able to identify what I did wrong? Thank you!My Pyside 2 implementation:
class TextOverDelegate(QStyledItemDelegate): def __init__(self, parent=None): super(TextOverDelegate, self).__init__(parent) def paint(self, painter, option, index): text = index.data(QtCore.Qt.UserRole) if(option.widget): style = option.widget else: style = QApplication.style() style.drawItemText(painter, option.rect,QtCore.Qt.AlignCenter, option.palette, option.state & QStyle.State_Enabled, text)
In the main UI window class all I set the new delegate as the list widget's current item delegate.
self.custom_delegate = TextOverDelegate() self.listWidget.setItemDelegate(self.custom_delegate)
@RaisinBread22 said in Overlaying text on top of QIcon in QListWidget in Pyside2:
style = option.widget
why do you assign widget to style? style has to be an instance of QStyle.
-
@RaisinBread22 said in Overlaying text on top of QIcon in QListWidget in Pyside2:
style = option.widget
why do you assign widget to style? style has to be an instance of QStyle.
-
On top of the above, you forgot to translate the first line:
QStyledItemDelegate::paint(painter,option,index);
. should be something likesuper(TextOverDelegate,self,painter,option,index).paint(painter,option,index)
Terrific, after making minor corrections I got text to display in the center of the Qicon! All I have left to do are 3 things.
- What method can I call on a QListWidgetItem to easily change the text to something different? Do I just call
item.setData(QtCore.Qt.UserRole, "New text goes here")
again? - What method can I call on a QListWidgetItem to easily disable the text?
- How do I make the text overlaying the QIcon red(it defaults to black) and change the font size?
Here's the corrected(working) subclass for reference:
class TextOverDelegate(QStyledItemDelegate): def __init__(self, parent=None): super(TextOverDelegate, self).__init__(parent) def paint(self, painter, option, index): super(TextOverDelegate,self).paint(painter,option,index) text = index.data(QtCore.Qt.UserRole) if(option.widget): style = option.widget.style() else: style = QApplication.style() style.drawItemText(painter, option.rect,QtCore.Qt.AlignCenter, option.palette, option.state & QStyle.State_Enabled, text)
Here's what it currently produces after creating the QListWidgetItem with
item = QtWidgets.QListWidgetItem(QtGui.QIcon(path), None)
and callingitem.setData(QtCore.Qt.UserRole, "Test Qicon text")
before finally callingself.listWidget.addItem(item)
- What method can I call on a QListWidgetItem to easily change the text to something different? Do I just call
-
Terrific, after making minor corrections I got text to display in the center of the Qicon! All I have left to do are 3 things.
- What method can I call on a QListWidgetItem to easily change the text to something different? Do I just call
item.setData(QtCore.Qt.UserRole, "New text goes here")
again? - What method can I call on a QListWidgetItem to easily disable the text?
- How do I make the text overlaying the QIcon red(it defaults to black) and change the font size?
Here's the corrected(working) subclass for reference:
class TextOverDelegate(QStyledItemDelegate): def __init__(self, parent=None): super(TextOverDelegate, self).__init__(parent) def paint(self, painter, option, index): super(TextOverDelegate,self).paint(painter,option,index) text = index.data(QtCore.Qt.UserRole) if(option.widget): style = option.widget.style() else: style = QApplication.style() style.drawItemText(painter, option.rect,QtCore.Qt.AlignCenter, option.palette, option.state & QStyle.State_Enabled, text)
Here's what it currently produces after creating the QListWidgetItem with
item = QtWidgets.QListWidgetItem(QtGui.QIcon(path), None)
and callingitem.setData(QtCore.Qt.UserRole, "Test Qicon text")
before finally callingself.listWidget.addItem(item)
- http://doc.qt.io/qt-5/qlistwidgetitem.html#setText
- What do you mean by "disable the text"?
- Qt style sheets: http://doc.qt.io/qt-5/stylesheet-examples.html
- What method can I call on a QListWidgetItem to easily change the text to something different? Do I just call
-
Terrific, after making minor corrections I got text to display in the center of the Qicon! All I have left to do are 3 things.
- What method can I call on a QListWidgetItem to easily change the text to something different? Do I just call
item.setData(QtCore.Qt.UserRole, "New text goes here")
again? - What method can I call on a QListWidgetItem to easily disable the text?
- How do I make the text overlaying the QIcon red(it defaults to black) and change the font size?
Here's the corrected(working) subclass for reference:
class TextOverDelegate(QStyledItemDelegate): def __init__(self, parent=None): super(TextOverDelegate, self).__init__(parent) def paint(self, painter, option, index): super(TextOverDelegate,self).paint(painter,option,index) text = index.data(QtCore.Qt.UserRole) if(option.widget): style = option.widget.style() else: style = QApplication.style() style.drawItemText(painter, option.rect,QtCore.Qt.AlignCenter, option.palette, option.state & QStyle.State_Enabled, text)
Here's what it currently produces after creating the QListWidgetItem with
item = QtWidgets.QListWidgetItem(QtGui.QIcon(path), None)
and callingitem.setData(QtCore.Qt.UserRole, "Test Qicon text")
before finally callingself.listWidget.addItem(item)
Do I just call item.setData(QtCore.Qt.UserRole, "New text goes here") again?
Correct
What method can I call on a QListWidgetItem to easily disable the text?
before
text = index.data(QtCore.Qt.UserRole)
addif(index.data(QtCore.Qt.UserRole+1)): return
Now you can use
item.setData(QtCore.Qt.UserRole+1,true)
to disable the text anditem.setData(QtCore.Qt.UserRole+1,false)
to enable it againHow do I make the text overlaying the QIcon red(it defaults to black) and change the font size?
replace
style.drawItemText(painter, option.rect,QtCore.Qt.AlignCenter, option.palette, option.state & QStyle.State_Enabled, text)
with (using, C++ here, sorry)painter->save(); QPen pen = painter->pen(); pen.setColor(Qt::red); // color painter->setPen(pen); QFont fnt = painter->font(); fnt.setPointSize(12); // font size painter->setFont(fnt); style->drawItemText(painter, option.rect, Qt::AlignCenter, option.palette, option.state & QStyle::State_Enabled, text.toString()); painter->restore();
- What method can I call on a QListWidgetItem to easily change the text to something different? Do I just call