Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Overlaying text on top of QIcon in QListWidget in Pyside2

Overlaying text on top of QIcon in QListWidget in Pyside2

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 7 Posters 3.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    RaisinBread22
    wrote on last edited by RaisinBread22
    #1

    Say I have a QListWidget in icon mode with multiple QIcons within it that looks like this:

    I populated the QListwidget very simply by looping over the file paths for the images I want to add to the QListWidget:

    for path in pathlist:
        self.HomeListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(path),None))
    
    

    How can I overlay text on top of the QIcon without modifying the image? I want the final result to look much like this:

    alt text

    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by dheerendra
      #2

      You need to write your own delegate which is inherited from QWidget. Re-implement the paintEvent(..) function to achieve this.

      void paintEvent(....) {
      QPainter p(this).
      p.drawPixmap(icon)
      p.drawRect(..)
      }

      Set this widget object using setItemWidget(...) function.

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      1 Reply Last reply
      0
      • R Offline
        R Offline
        RaisinBread22
        wrote on last edited by RaisinBread22
        #3

        @dheerendra Thanks for your response. Do you have a link to a simple, complete example of somebody doing this? I haven't written my own delegate before, and all of the examples I've been able to find over the past few hours seem unnecessarily complicated for what I'm doing and It's very overwhelming. All the examples I've seen are inheriting from QItemDelegate, not QWidget. Cheers!

        1 Reply Last reply
        0
        • dheerendraD Offline
          dheerendraD Offline
          dheerendra
          Qt Champions 2022
          wrote on last edited by dheerendra
          #4

          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
          @Community Service
          Certified Qt Specialist
          http://www.pthinks.com

          JonBJ 1 Reply Last reply
          1
          • dheerendraD dheerendra

            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.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @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...?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              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.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              3
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #7

                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 passing Qt::UserRole

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                R 1 Reply Last reply
                3
                • VRoninV VRonin

                  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 passing Qt::UserRole

                  R Offline
                  R Offline
                  RaisinBread22
                  wrote on last edited by RaisinBread22
                  #8

                  @VRonin

                  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)
                  
                  jsulmJ 1 Reply Last reply
                  0
                  • R RaisinBread22

                    @VRonin

                    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)
                    
                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @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.

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    mrjjM 1 Reply Last reply
                    1
                    • jsulmJ jsulm

                      @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.

                      mrjjM Offline
                      mrjjM Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on last edited by mrjj
                      #10

                      @jsulm
                      Hi
                      Maybe he meant

                      if(option.widget):
                      style = option.widget.style()
                      else:
                      style = QApplication.style()

                      aka use widget style / use global style

                      1 Reply Last reply
                      2
                      • VRoninV Offline
                        VRoninV Offline
                        VRonin
                        wrote on last edited by
                        #11

                        On top of the above, you forgot to translate the first line: QStyledItemDelegate::paint(painter,option,index);. should be something like super(TextOverDelegate,self,painter,option,index).paint(painter,option,index)

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        R 1 Reply Last reply
                        4
                        • VRoninV VRonin

                          On top of the above, you forgot to translate the first line: QStyledItemDelegate::paint(painter,option,index);. should be something like super(TextOverDelegate,self,painter,option,index).paint(painter,option,index)

                          R Offline
                          R Offline
                          RaisinBread22
                          wrote on last edited by RaisinBread22
                          #12

                          @VRonin

                          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.

                          1. 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?
                          2. What method can I call on a QListWidgetItem to easily disable the text?
                          3. 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 calling item.setData(QtCore.Qt.UserRole, "Test Qicon text") before finally calling self.listWidget.addItem(item)

                          alt text

                          jsulmJ VRoninV 2 Replies Last reply
                          1
                          • R RaisinBread22

                            @VRonin

                            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.

                            1. 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?
                            2. What method can I call on a QListWidgetItem to easily disable the text?
                            3. 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 calling item.setData(QtCore.Qt.UserRole, "Test Qicon text") before finally calling self.listWidget.addItem(item)

                            alt text

                            jsulmJ Offline
                            jsulmJ Offline
                            jsulm
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            @RaisinBread22

                            1. http://doc.qt.io/qt-5/qlistwidgetitem.html#setText
                            2. What do you mean by "disable the text"?
                            3. Qt style sheets: http://doc.qt.io/qt-5/stylesheet-examples.html

                            https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            0
                            • R RaisinBread22

                              @VRonin

                              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.

                              1. 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?
                              2. What method can I call on a QListWidgetItem to easily disable the text?
                              3. 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 calling item.setData(QtCore.Qt.UserRole, "Test Qicon text") before finally calling self.listWidget.addItem(item)

                              alt text

                              VRoninV Offline
                              VRoninV Offline
                              VRonin
                              wrote on last edited by VRonin
                              #14

                              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) add

                              if(index.data(QtCore.Qt.UserRole+1)):
                                  return
                              

                              Now you can use item.setData(QtCore.Qt.UserRole+1,true) to disable the text and item.setData(QtCore.Qt.UserRole+1,false) to enable it again

                              How 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();
                              

                              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                              ~Napoleon Bonaparte

                              On a crusade to banish setIndexWidget() from the holy land of Qt

                              1 Reply Last reply
                              4

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved