Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. PySide2 or Pyqt5 - Lost selection highlighting on custom widget when adding to a QTreeViewItem in “IconMode”
Forum Updated to NodeBB v4.3 + New Features

PySide2 or Pyqt5 - Lost selection highlighting on custom widget when adding to a QTreeViewItem in “IconMode”

Scheduled Pinned Locked Moved Solved Qt for Python
pyside2qt for python
7 Posts 2 Posters 1.7k 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.
  • J Offline
    J Offline
    jball
    wrote on last edited by
    #1

    I am trying to create a list of custom widgets where a user clicks them to open pictures/movies. I have everything working but I have lost the selection highlighting that usually comes with an item.

    I know it's not there because I'm using a custom widget. How do I get selection highlight on the widget? I would like the item to show a transparent layer of blue.

    Curious, when I change the view mode to ListMode you can see the blue selection. I have commented it out in the example code.

    He is a striped back example, well as striped back as I can get it anyway. Switch the list views and select an item to see the different behaviour.

    import sys
    from datetime import datetime
    from PySide2 import QtWidgets
    from PySide2 import QtCore
    from PySide2 import QtGui
    
    
    class EntryWidget(QtWidgets.QWidget):
    
        def __init__(self):
            super(EntryWidget, self).__init__()
            self.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
    
            # controls
            self.thumbnail = QtWidgets.QLabel()
            self.version = QtWidgets.QLabel()
            self.date = QtWidgets.QLabel()
            self.name = QtWidgets.QLabel()
            self.name.setAlignment(QtCore.Qt.AlignCenter)
            self.author = QtWidgets.QLabel()
            self.author.setAlignment(QtCore.Qt.AlignRight)
            self.dummy = QtWidgets.QLabel(" ")
    
            # layout
            main_layout = QtWidgets.QVBoxLayout()
    
            main_layout.setContentsMargins(0, 0, 0, 0)
            main_layout.setSpacing(0)
            main_layout.addWidget(self.name)
            main_layout.addWidget(self.thumbnail)
            main_layout.addWidget(self.version)
            main_layout.addWidget(self.date)
            main_layout.addWidget(self.author)
            main_layout.addWidget(self.dummy)
            main_layout.addStretch()
    
            self.setLayout(main_layout)
    
        def set_size(self, w, h):
            self.thumbnail.setFixedSize(w, h)
    
        def set_version(self, name):
            self.version.setText(" Version:" + str(name))
    
        def set_date(self, name):
            date_string = " Date: {0}/{1}/{2}\n Time: {3}:{4}:{5}".format(
                str(name.day).zfill(2),
                str(name.month).zfill(2),
                name.year,
                name.hour,
                name.minute,
                name.second)
            self.date.setText(date_string)
    
        def set_name(self, name):
            self.name.setText(name)
    
        def set_author(self, name):
            self.author.setText(name + " ")
    
    class QuickExample(QtWidgets.QDialog):
        def __init__(self, parent=None):
            super(QuickExample, self).__init__(parent)
            self.resize(500, 500)
            layout = QtWidgets.QVBoxLayout()
    
            media_list = QtWidgets.QListWidget(self)
    
            # switch the views and select an item
            media_list.setViewMode(QtWidgets.QListWidget.IconMode)
            # media_list.setViewMode(QtWidgets.QListWidget.ListMode)
    
            media_list.setResizeMode(QtWidgets.QListWidget.Adjust)
            media_list.setMovement(QtWidgets.QListWidget.Static)
            media_list.setSpacing(5)
    
            # dummy media, usually sourced from database
            media = [
                {"version": 1, "date": datetime.now(), "name": "Entry 01", "author": "Bob"},
                {"version": 2, "date": datetime.now(), "name": "Entry 02", "author": "John"}
            ]
    
            for i in media:
                # Create media Entry
                entry = EntryWidget()
                entry.set_version(i["version"])
                entry.set_date(i["date"])
                entry.set_size(128, 72)
                entry.set_name(i["name"])
                entry.set_author(i["author"])
    
                # Create QListWidgetItem
                media_item = QtWidgets.QListWidgetItem(media_list)
    
                # Set size hint
                media_item.setSizeHint(entry.sizeHint())
    
                # Add QListWidgetItem into QListWidget
                media_list.addItem(media_item)
                media_list.setItemWidget(media_item, entry)
    
            layout.addWidget(media_list)
            self.setLayout(layout)
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        example = QuickExample()
        example.show()
        sys.exit(app.exec_())
    
    1 Reply Last reply
    0
    • J Offline
      J Offline
      jball
      wrote on last edited by
      #7

      Well, I have found a hacky way of doing this which works fo me. I added some blank text to the QListWidgetItem and made the font really big. This brought back the highlighting for the item.

      media_item.setText("  ") # set the item with a  dummy string
      media_item.setFont(QFont('Verdana', 180)) # make the font big so it covers the whole widget
      

      After some research I found that using QListView and QItemDelegate is way to do this. I couldn't find a good example/tutorial using PyQt5 so I will just use this for now.

      Here is the hacked code

      from PySide2.QtCore    import *
      from PySide2.QtGui     import *
      from PySide2.QtWidgets import *
      
      from sys      import exit     as sysExit
      from datetime import datetime as dtDateTime
      
      class EntryWidget(QWidget):
          def __init__(self):
              QWidget.__init__(self)
      
              self.setCursor(QCursor(Qt.PointingHandCursor))
              self.setFocusPolicy(Qt.StrongFocus)  # Sets the Highlight when it has focus
      
            # Controls
              self.thumbnail = QLabel()
              self.version = QLabel()
              self.date = QLabel()
              self.name = QLabel()
              self.name.setAlignment(Qt.AlignCenter)
              self.author = QLabel()
              self.author.setAlignment(Qt.AlignRight)
              self.dummy = QLabel(" ")
      
            # Layout Container
              VBox = QVBoxLayout()
              VBox.setContentsMargins(0, 0, 0, 0)
              VBox.setSpacing(0)
              VBox.addWidget(self.name)
              VBox.addWidget(self.thumbnail)
              VBox.addWidget(self.version)
              VBox.addWidget(self.date)
              VBox.addWidget(self.author)
              VBox.addWidget(self.dummy)
              VBox.addStretch()
      
              self.setLayout(VBox)
      
          def set_size(self, w, h):
              self.thumbnail.setFixedSize(w, h)
      
          def set_version(self, name):
              self.version.setText(" Version:" + str(name))
      
          def set_date(self, name):
              date_string = " Date: {0}/{1}/{2}\n Time: {3}:{4}:{5}".format(
                  str(name.day).zfill(2),
                  str(name.month).zfill(2),
                  name.year,
                  name.hour,
                  name.minute,
                  name.second)
              self.date.setText(date_string)
      
          def set_name(self, name):
              self.name.setText(name)
      
          def set_author(self, name):
              self.author.setText(name + " ")
      
      class QuickExample(QDialog):
          def __init__(self):
              QDialog.__init__(self)
              self.resize(500, 500)
      
              media_list = QListWidget(self)
      
              # switch the views and select an item
              media_list.setViewMode(QListWidget.IconMode)
      
              media_list.setResizeMode(QListWidget.Adjust)
              media_list.setMovement(QListWidget.Static)
              media_list.setSpacing(5)
      
              # dummy media, usually sourced from database
              media = [
                  {"version": 1, "date": dtDateTime.now(), "name": "Entry 01", "author": "Bob"},
                  {"version": 2, "date": dtDateTime.now(), "name": "Entry 02", "author": "John"}
              ]
      
              for i in media:
                  # Create media Entry
                  entry = EntryWidget()
                  entry.set_version(i["version"])
                  entry.set_date(i["date"])
                  entry.set_size(128, 72)
                  entry.set_name(i["name"])
                  entry.set_author(i["author"])
      
                  # Create QListWidgetItem
                  media_item = QListWidgetItem(media_list)
                  
                  ###########
                  # the fix #
                  ###########
      
                  media_item.setText("  ") # set the item with a dummy string
                  media_item.setFont(QFont('Verdana', 180)) # make the font big so it covers the whole widget
      
                  # Set size hint
                  media_item.setSizeHint(entry.sizeHint())
      
                  # Add QListWidgetItem into QListWidget
                  media_list.addItem(media_item)
                  media_list.setItemWidget(media_item, entry)
      
              VBox = QVBoxLayout()
              VBox.addWidget(media_list)
      
              self.setLayout(VBox)
      
      
      if __name__ == "__main__":
          MainEventHandler = QApplication([])
          MainApplication = QuickExample()
          MainApplication.show()
          sysExit(MainEventHandler.exec_())
      
      1 Reply Last reply
      0
      • J Offline
        J Offline
        jball
        wrote on last edited by jball
        #2

        Thanks for replying. I am trying to create a gallery where a user can select an item and it will display a picture. I have this working but there is no way of telling which item is selected.

        If you switch the above code to "IconMode" (uncomment this line)

        media_list.setViewMode(QtWidgets.QListWidget.ListMode)
        

        Then select an item you will see a blue box around the selected item. This is not the case for IconMode. If you select an item there is no indication that it has been selected.

        Thats pretty much it. I'm not sure why it looses the selection colour when you switch modes, I'd expect the behaviour to be the same.

        1 Reply Last reply
        0
        • J Offline
          J Offline
          jball
          wrote on last edited by
          #3

          @Denni-0 Thank you.

          1 Reply Last reply
          0
          • J Offline
            J Offline
            jball
            wrote on last edited by jball
            #4

            Thanks for taking the time to adjust my code, but I'm still not seeing an item highlight on IconMode. I have tested it in PySide2 and PyQt5. Did you see highlighting in IconMode?

            Thanks for the comments regarding super(), I have done it ever since I start learning PySide/PyQt, just a habit.

            1 Reply Last reply
            0
            • J Offline
              J Offline
              jball
              wrote on last edited by jball
              #5

              Sorry for the confusion but it is IconView I would like to use. I was using the list view as an example on how it works there and not on IconView.

              If you add a QListWidgetItem without a custom widget, the selection highlighting works, example below. For some reason my custom widget is blowing away the highlighting.

              Now if I can get my custom widget in IconMode to have the highlighting, I will be very happy.

              Screen Shot 2020-04-09 at 10.48.34 AM.png

              Example code (you will need an image to see icon, but you can still see it works without it)

              from PyQt5.QtCore import *
              from PyQt5.QtGui import *
              from PyQt5.QtWidgets import *
              
              from sys import exit as sysExit
              from datetime import datetime as dtDateTime
              
              
              class QuickExample(QDialog):
                  def __init__(self):
                      QDialog.__init__(self)
                      self.resize(500, 500)
                      media_list = QListWidget(self)
              
                    # switch the views and select an item
                      media_list.setViewMode(QListWidget.IconMode)
                      # media_list.setViewMode(QListWidget.ListMode)
              
                      media_list.setResizeMode(QListWidget.Adjust)
                      media_list.setMovement(QListWidget.Static)
                      media_list.setSpacing(5)
                      media_list.setIconSize(QSize(72, 128))
              
                      # dummy media, usually sourced from database
                      media = [
                          {"version": 1, "date": dtDateTime.now(), "name": "Entry 01", "author": "Bob"},
                          {"version": 2, "date": dtDateTime.now(), "name": "Entry 02", "author": "John"}
                      ]
              
                      for i in media:
                          # Create QListWidgetItem
                          media_item = QListWidgetItem(media_list)
                          media_item.setText(i["name"])
                          media_item.setIcon(QIcon(r"/Users/jeremyball/Desktop/seq/soul.jpg"))
              
                          # Add QListWidgetItem into QListWidget
                          media_list.addItem(media_item)
              
                      VBox = QVBoxLayout()
                      VBox.addWidget(media_list)
              
                      self.setLayout(VBox)
              
              
              if __name__ == "__main__":
              
                  MainEventHandler = QApplication([])
                  MainApplication = QuickExample()
                  MainApplication.show()
                  sysExit(MainEventHandler.exec_())
              
              
              1 Reply Last reply
              0
              • J Offline
                J Offline
                jball
                wrote on last edited by jball
                #6

                I think I'm confusing things more with that last example. I was trying to show that it is working on a listWidgetItem without a custom widget.

                What I would like is, selection highlighting on my custom Qwidget "EntryWidget".

                Here is the code you previously supplied where the problem lies. There is no selection highlighting on the icons.

                from PySide2.QtCore    import *
                from PySide2.QtGui     import *
                from PySide2.QtWidgets import *
                
                from sys      import exit     as sysExit
                from datetime import datetime as dtDateTime
                
                class EntryWidget(QWidget):
                    def __init__(self):
                      # First you should not use super( ) in Python as it introduces 4 known issues 
                      # that must be handled properly. Further there were still actual bugs within
                      # the usage of super( ) when used in Python. Yes while super( ) works fine 
                      # within C++ it does not work as seamlessly within Python due to the major 
                      # differences between these 2 languages. Next the reason it was created was 
                      # to handle a rather rare issue and unless you are doing some complicated 
                      # inheritance you will most likely never run into this extremely rare issue
                      # However the 4 major issues that get included by using super( ) you are much 
                      # more likely to occur than that rare issue its meant for to solve. Of course
                      # using the basic explicit method, as follows, does not cause these issues and 
                      # is as just as simple as using `super( )` further you do not actually gain 
                      # anything useful by using `super( )` in Python that could not be done in a 
                      # much safer manner.
                      # super(EntryWidget, self).__init__()
                        QWidget.__init__(self)
                
                        self.setCursor(QCursor(Qt.PointingHandCursor))
                        self.setFocusPolicy(Qt.StrongFocus)  # Sets the Highlight when it has focus
                
                      # Controls
                        self.thumbnail = QLabel()
                        self.version = QLabel()
                        self.date = QLabel()
                        self.name = QLabel()
                        self.name.setAlignment(Qt.AlignCenter)
                        self.author = QLabel()
                        self.author.setAlignment(Qt.AlignRight)
                        self.dummy = QLabel(" ")
                
                      # Layout Container
                        VBox = QVBoxLayout()
                        VBox.setContentsMargins(0, 0, 0, 0)
                        VBox.setSpacing(0)
                        VBox.addWidget(self.name)
                        VBox.addWidget(self.thumbnail)
                        VBox.addWidget(self.version)
                        VBox.addWidget(self.date)
                        VBox.addWidget(self.author)
                        VBox.addWidget(self.dummy)
                        VBox.addStretch()
                
                        self.setLayout(VBox)
                
                    def set_size(self, w, h):
                        self.thumbnail.setFixedSize(w, h)
                
                    def set_version(self, name):
                        self.version.setText(" Version:" + str(name))
                
                    def set_date(self, name):
                        date_string = " Date: {0}/{1}/{2}\n Time: {3}:{4}:{5}".format(
                            str(name.day).zfill(2),
                            str(name.month).zfill(2),
                            name.year,
                            name.hour,
                            name.minute,
                            name.second)
                        self.date.setText(date_string)
                
                    def set_name(self, name):
                        self.name.setText(name)
                
                    def set_author(self, name):
                        self.author.setText(name + " ")
                
                class QuickExample(QDialog):
                    def __init__(self):
                      # Per as above 
                      # super(QuickExample, self).__init__(parent)
                        QDialog.__init__(self)
                        self.resize(500, 500)
                
                        media_list = QListWidget(self)
                
                      # switch the views and select an item
                        media_list.setViewMode(QListWidget.IconMode)
                
                        media_list.setResizeMode(QListWidget.Adjust)
                        media_list.setMovement(QListWidget.Static)
                        media_list.setSpacing(5)
                
                        # dummy media, usually sourced from database
                        media = [
                            {"version": 1, "date": dtDateTime.now(), "name": "Entry 01", "author": "Bob"},
                            {"version": 2, "date": dtDateTime.now(), "name": "Entry 02", "author": "John"}
                        ]
                
                        for i in media:
                            # Create media Entry
                            entry = EntryWidget()
                            entry.set_version(i["version"])
                            entry.set_date(i["date"])
                            entry.set_size(128, 72)
                            entry.set_name(i["name"])
                            entry.set_author(i["author"])
                
                            # Create QListWidgetItem
                            media_item = QListWidgetItem(media_list)
                
                            # Set size hint
                            media_item.setSizeHint(entry.sizeHint())
                
                            # Add QListWidgetItem into QListWidget
                            media_list.addItem(media_item)
                            media_list.setItemWidget(media_item, entry)
                
                      # Not needed until here and this keeps like things grouped
                        VBox = QVBoxLayout()
                        VBox.addWidget(media_list)
                
                        self.setLayout(VBox)
                
                
                if __name__ == "__main__":
                  # If you are not using Command Line arguements then do not include 
                  # them. However if you do plan to use Command Line arguements then
                  # I strongly suggest you look into using the argparser library as
                  # it handles them more cleanly, intuitively, and efficiently
                  # app = QtWidgets.QApplication(sys.argv)
                    MainEventHandler = QApplication([])
                
                    MainApplication = QuickExample()
                    MainApplication.show()
                
                  # Just so you know this is actually still PyQt4 style as this
                  # has changed in Qt5 but PySide2 is still behind the ball on
                  # this -- MainEventHandler.exec() < this is all that is needed
                  # now in Qt5 as opposed to Qt4 and PySide2 hopefully the will
                  # fix this minor issue soon
                    sysExit(MainEventHandler.exec_())
                
                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  jball
                  wrote on last edited by
                  #7

                  Well, I have found a hacky way of doing this which works fo me. I added some blank text to the QListWidgetItem and made the font really big. This brought back the highlighting for the item.

                  media_item.setText("  ") # set the item with a  dummy string
                  media_item.setFont(QFont('Verdana', 180)) # make the font big so it covers the whole widget
                  

                  After some research I found that using QListView and QItemDelegate is way to do this. I couldn't find a good example/tutorial using PyQt5 so I will just use this for now.

                  Here is the hacked code

                  from PySide2.QtCore    import *
                  from PySide2.QtGui     import *
                  from PySide2.QtWidgets import *
                  
                  from sys      import exit     as sysExit
                  from datetime import datetime as dtDateTime
                  
                  class EntryWidget(QWidget):
                      def __init__(self):
                          QWidget.__init__(self)
                  
                          self.setCursor(QCursor(Qt.PointingHandCursor))
                          self.setFocusPolicy(Qt.StrongFocus)  # Sets the Highlight when it has focus
                  
                        # Controls
                          self.thumbnail = QLabel()
                          self.version = QLabel()
                          self.date = QLabel()
                          self.name = QLabel()
                          self.name.setAlignment(Qt.AlignCenter)
                          self.author = QLabel()
                          self.author.setAlignment(Qt.AlignRight)
                          self.dummy = QLabel(" ")
                  
                        # Layout Container
                          VBox = QVBoxLayout()
                          VBox.setContentsMargins(0, 0, 0, 0)
                          VBox.setSpacing(0)
                          VBox.addWidget(self.name)
                          VBox.addWidget(self.thumbnail)
                          VBox.addWidget(self.version)
                          VBox.addWidget(self.date)
                          VBox.addWidget(self.author)
                          VBox.addWidget(self.dummy)
                          VBox.addStretch()
                  
                          self.setLayout(VBox)
                  
                      def set_size(self, w, h):
                          self.thumbnail.setFixedSize(w, h)
                  
                      def set_version(self, name):
                          self.version.setText(" Version:" + str(name))
                  
                      def set_date(self, name):
                          date_string = " Date: {0}/{1}/{2}\n Time: {3}:{4}:{5}".format(
                              str(name.day).zfill(2),
                              str(name.month).zfill(2),
                              name.year,
                              name.hour,
                              name.minute,
                              name.second)
                          self.date.setText(date_string)
                  
                      def set_name(self, name):
                          self.name.setText(name)
                  
                      def set_author(self, name):
                          self.author.setText(name + " ")
                  
                  class QuickExample(QDialog):
                      def __init__(self):
                          QDialog.__init__(self)
                          self.resize(500, 500)
                  
                          media_list = QListWidget(self)
                  
                          # switch the views and select an item
                          media_list.setViewMode(QListWidget.IconMode)
                  
                          media_list.setResizeMode(QListWidget.Adjust)
                          media_list.setMovement(QListWidget.Static)
                          media_list.setSpacing(5)
                  
                          # dummy media, usually sourced from database
                          media = [
                              {"version": 1, "date": dtDateTime.now(), "name": "Entry 01", "author": "Bob"},
                              {"version": 2, "date": dtDateTime.now(), "name": "Entry 02", "author": "John"}
                          ]
                  
                          for i in media:
                              # Create media Entry
                              entry = EntryWidget()
                              entry.set_version(i["version"])
                              entry.set_date(i["date"])
                              entry.set_size(128, 72)
                              entry.set_name(i["name"])
                              entry.set_author(i["author"])
                  
                              # Create QListWidgetItem
                              media_item = QListWidgetItem(media_list)
                              
                              ###########
                              # the fix #
                              ###########
                  
                              media_item.setText("  ") # set the item with a dummy string
                              media_item.setFont(QFont('Verdana', 180)) # make the font big so it covers the whole widget
                  
                              # Set size hint
                              media_item.setSizeHint(entry.sizeHint())
                  
                              # Add QListWidgetItem into QListWidget
                              media_list.addItem(media_item)
                              media_list.setItemWidget(media_item, entry)
                  
                          VBox = QVBoxLayout()
                          VBox.addWidget(media_list)
                  
                          self.setLayout(VBox)
                  
                  
                  if __name__ == "__main__":
                      MainEventHandler = QApplication([])
                      MainApplication = QuickExample()
                      MainApplication.show()
                      sysExit(MainEventHandler.exec_())
                  
                  1 Reply Last reply
                  0

                  • Login

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