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
Forum Updated to NodeBB v4.3 + New Features

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 2 Watching
  • 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.
  • 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