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. QAbstractTableModel - checkbox not showing checked
Forum Updated to NodeBB v4.3 + New Features

QAbstractTableModel - checkbox not showing checked

Scheduled Pinned Locked Moved Unsolved Qt for Python
8 Posts 5 Posters 2.0k 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.
  • T Offline
    T Offline
    Todd Banister
    wrote on last edited by
    #1

    I have a set of QAbstractTableModels that display data from database tables which all have a checkbox in the first column (indicating which rows have been selected). This code has worked flawlessly now for over a year - until very recently.

    Now the code still runs (without any errors) and from debugging, the checkboxes in the appropriate rows respond as if they were checked, but no actual check is visible in their checkboxes. If I click on one of the selected rows, the check suddenly appears in the checkbox but the row doesn't initiate any update or such. From everything I can determine, the checkboxes are correctly checked - they simply are not displaying correctly.

    There have been no coding changes at all (I've even restored code from backups to verify) - but there has been environment updates. These updates include version 12.3.1 on my Mac as well as various Python package updates (PySide6 6.3, Pandas 1.4.2, etc).

    The really interesting part is if I run the exact same code in my Fedora 34 VM, everything responds as normal and the checks appear in the appropriate checkboxes (without requiring any additional clicks). Its only on my Mac that I am having this issue.

    I have tried to load previous versions of the Python Packages, but so far no change in behavior. I have experimented with updating the code to force the "refresh" of the QTableView and/or the QAbstractTableModel by editing a dataChanged event - but no change in behavior at all. At this point, I'm stumped as to how to get the UI back to a working condition.

    Thanks,
    TB

    JonBJ wilsliW 2 Replies Last reply
    1
    • T Todd Banister

      I have a set of QAbstractTableModels that display data from database tables which all have a checkbox in the first column (indicating which rows have been selected). This code has worked flawlessly now for over a year - until very recently.

      Now the code still runs (without any errors) and from debugging, the checkboxes in the appropriate rows respond as if they were checked, but no actual check is visible in their checkboxes. If I click on one of the selected rows, the check suddenly appears in the checkbox but the row doesn't initiate any update or such. From everything I can determine, the checkboxes are correctly checked - they simply are not displaying correctly.

      There have been no coding changes at all (I've even restored code from backups to verify) - but there has been environment updates. These updates include version 12.3.1 on my Mac as well as various Python package updates (PySide6 6.3, Pandas 1.4.2, etc).

      The really interesting part is if I run the exact same code in my Fedora 34 VM, everything responds as normal and the checks appear in the appropriate checkboxes (without requiring any additional clicks). Its only on my Mac that I am having this issue.

      I have tried to load previous versions of the Python Packages, but so far no change in behavior. I have experimented with updating the code to force the "refresh" of the QTableView and/or the QAbstractTableModel by editing a dataChanged event - but no change in behavior at all. At this point, I'm stumped as to how to get the UI back to a working condition.

      Thanks,
      TB

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

      @Todd-Banister
      Hi. This sounds like something which you could reproduce in 20-odd lines of standalone code. You could also try it with just, say, a QStandardItemModel or even a QTableWidget? That's what I would try.

      Then post the code, a screenshot of how it doesn't show right, and a precise description of MacOS version and Qt version. (My thought would be it should not be related to Python/Pandas/PySide.)

      I am not a Mac user, but plenty people here are and they might see how it looks for them/advise.

      1 Reply Last reply
      0
      • T Offline
        T Offline
        Todd Banister
        wrote on last edited by
        #3

        I continued to look into the issue today and found that my Mac and my Fedora VM actually had some different versions of some packages.

        I used pyenv to create a clean version of Python 3.10.4 and installed all the same Python packages that are in my Fedora VM (which isn't having the issue). The issue went away.

        I then started upgrading the packages one by one and testing. I left PySide6 as the last one to test. I then started upgrading PySide6 to each individual higher version and testing. I found that if I used PySide6 version 6.2.3 the code worked as expected. Once I upgraded PySide6 to version 6.2.4 - the checkboxes suddenly stopped showing the checks. I downgraded back to 6.2.3 and the issue went away again.

        So what changed in PySide6 from 6.2.3 to 6.2.4?

        JonBJ 1 Reply Last reply
        2
        • T Todd Banister

          I continued to look into the issue today and found that my Mac and my Fedora VM actually had some different versions of some packages.

          I used pyenv to create a clean version of Python 3.10.4 and installed all the same Python packages that are in my Fedora VM (which isn't having the issue). The issue went away.

          I then started upgrading the packages one by one and testing. I left PySide6 as the last one to test. I then started upgrading PySide6 to each individual higher version and testing. I found that if I used PySide6 version 6.2.3 the code worked as expected. Once I upgraded PySide6 to version 6.2.4 - the checkboxes suddenly stopped showing the checks. I downgraded back to 6.2.3 and the issue went away again.

          So what changed in PySide6 from 6.2.3 to 6.2.4?

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

          @Todd-Banister
          Like I suggested, have you considered that the change might be in the Qt version and not in the PySide version? That would be my guess, and where I would start looking for changes. Of course if you had C++ you could verify that the change is in Qt and not in PySide, from 6.2.3 to 6.2.4. https://code.qt.io/cgit/qt/qtreleasenotes.git/about/qt/6.2.4/release-note.md

          1 Reply Last reply
          1
          • CristianMaureiraC Offline
            CristianMaureiraC Offline
            CristianMaureira
            wrote on last edited by
            #5

            Just to complement @JonB answer, you can check the 6.2.4 changes here: https://code.qt.io/cgit/pyside/pyside-setup.git/tree/doc/changelogs/changes-6.2.4 if none of those things sound like could generate your problem, it could be a Qt problem.
            PS: If you want to use PySide 6.3.0 please uninstall your current installation and install it again. The change in the package structure has an issue when upgrading from 6.2.x

            1 Reply Last reply
            1
            • T Todd Banister

              I have a set of QAbstractTableModels that display data from database tables which all have a checkbox in the first column (indicating which rows have been selected). This code has worked flawlessly now for over a year - until very recently.

              Now the code still runs (without any errors) and from debugging, the checkboxes in the appropriate rows respond as if they were checked, but no actual check is visible in their checkboxes. If I click on one of the selected rows, the check suddenly appears in the checkbox but the row doesn't initiate any update or such. From everything I can determine, the checkboxes are correctly checked - they simply are not displaying correctly.

              There have been no coding changes at all (I've even restored code from backups to verify) - but there has been environment updates. These updates include version 12.3.1 on my Mac as well as various Python package updates (PySide6 6.3, Pandas 1.4.2, etc).

              The really interesting part is if I run the exact same code in my Fedora 34 VM, everything responds as normal and the checks appear in the appropriate checkboxes (without requiring any additional clicks). Its only on my Mac that I am having this issue.

              I have tried to load previous versions of the Python Packages, but so far no change in behavior. I have experimented with updating the code to force the "refresh" of the QTableView and/or the QAbstractTableModel by editing a dataChanged event - but no change in behavior at all. At this point, I'm stumped as to how to get the UI back to a working condition.

              Thanks,
              TB

              wilsliW Offline
              wilsliW Offline
              wilsli
              wrote on last edited by
              #6

              @Todd-Banister I have the same problem on my Mac! I checked that the value saved in the Qt.CheckStateRole was correct, but the QTableView only rendered everything as Qt.Unchecked. What's even worse in my case is this issue made my setData() only worked for checking the unchecked item while couldn't uncheck those items actually have value of Qt.Checked. See below screenshot, when I click the checkbox of the second row, the value of "included" column will be changed into "Yes", but the checkbox remained unchecked; I click the checkbox in row[0] and row[2], nothing happen.
              SCR-20220617-g0f.png
              my model code is:

              class pandasModel(QtCore.QAbstractTableModel):
                  def __init__(self, data:pd.DataFrame):
                      super(pandasModel, self).__init__()
                      self._data = data
              
                  def rowCount(self, index):
                      return self._data.shape[0]
                  
                  def columnCount(self, index):
                      return self._data.shape[1]
              
                  def data(self, index, role):
                      row = index.row()
                      column = index.column()
                      value = self._data.iloc[row, column]
                      if role == QtCore.Qt.DisplayRole:
                          if value == True:
                              return "Yes"
                          elif value == False:
                              return "No"
                          else:
                              return str(value)
                      if role == QtCore.Qt.CheckStateRole and column == 2:
                          if value == True:
                              return QtCore.Qt.Checked
                          else:
                              return QtCore.Qt.Unchecked
              
                  def setData(self, index, value, role):
                      row = index.row()
                      column = index.column()
                      if role == QtCore.Qt.CheckStateRole and column == 2:
                          if value == QtCore.Qt.Checked:
                              self._data.iloc[row, column] = True
                              self.dataChanged.emit(index, index)
                          elif value == QtCore.Qt.Unchecked:
                              self._data.iloc[row, column] = False
                              self.dataChanged.emit(index, index)
                          return True
                      return False
              
                  def flags(self, index):
                      flags = super().flags(index)
                      if index.column() == 2:
                          flags |= QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable
                      return flags
              
                  def headerData(self, section, orientation, role):
                      # section is the index of the column/row.
                      if role == QtCore.Qt.DisplayRole:
                          if orientation == QtCore.Qt.Horizontal:
                              return str(self._data.columns[section])
                          elif orientation == QtCore.Qt.Vertical:
                              return str(self._data.index[section])
              

              I haven't try rewriting the delegate, maybe there was something wrong with the default delegate of this version of the QTableView. BTW, I'm using excatly the same versions of PySide6(6.3).

              1 Reply Last reply
              0
              • N Offline
                N Offline
                Nike_Water
                wrote on last edited by
                #7

                Maybe you can use the "QStandardItem" to store the checkstate:

                def __init__(self, data:pd.DataFrame):
                        super(pandasModel, self).__init__()
                        self._data = data
                        #adding the checkstate. In your model:column 2
                        self.col = 2
                        col = self.col
                        for row in range(len(self._data.iloc[:,col])):
                               value = self._data.iloc[row,col]
                               item = QStandardItem(value)
                               item.setCheckable(True)
                               item.setCheckState(QtCore.Qt.Checked if value else QtCore.Qt.unChecked
                               self._data.iloc[row,col] = item
                

                for func data:

                ...
                   if role == QtCore.Qt.DisplayRole:
                       if column == self.col:
                           value1 = value.text()
                           value = "Yes" if value1 == 'True' else "No"
                       return str(value)
                ...
                   if role == QtCore.Qt.CheckStateRole:
                      if column == self.col:
                          if self._data.iloc[index.row(),index.column()].checkState() == Qt.Checked:
                               return QtCore.Qt.Checked
                          else:
                               return QtCore.Qt.Unchecked             
                ...
                if role == Qt.ItemDataRole.EditRole:
                     if column == self.col:
                          value = "Yes" if value.text() == 'True' else "No"
                      return str(value)
                

                You can modify "setData" according to func "data"

                You may modify func 'flags' as following:

                def flags(self, index):
                        flags = super().flags(index)
                        if index.column() == self.col:
                            flags |= QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsSelectable | ItemIsEditable
                        return flags
                
                1 Reply Last reply
                1
                • CristianMaureiraC Offline
                  CristianMaureiraC Offline
                  CristianMaureira
                  wrote on last edited by
                  #8

                  For future readers, this issue was addressed here https://bugreports.qt.io/browse/PYSIDE-1930 and will be fixed in 6.3.2

                  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