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. QStandardItemModel doesn't update QTableView

QStandardItemModel doesn't update QTableView

Scheduled Pinned Locked Moved Solved Qt for Python
pysidepythonqt for python
6 Posts 2 Posters 607 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.
  • D Offline
    D Offline
    demberto
    wrote on last edited by demberto
    #1
    class EventsTableModel(QStandardItemModel):
        EVENT = 1000
    
        def __init__(self, et: EventTree, show_only: list[EventEnum]) -> None:
            super().__init__(None)
            self.et = et
            self.events = tuple(et.get(*show_only))
            self.set_horizontal_header_labels(["ID", "Value"])
    
            for event in self.events:
                id_item = QStandardItem(str(event.id))
                id_item.set_editable(False)
                val_item = QStandardItem()
                val_item.set_data(event, self.EVENT)
    
                try:
                    val_item.set_data(event.value, Qt.ItemDataRole.DisplayRole)
                except NotImplementedError:
                    continue
                self.append_row((id_item, val_item))
    
        def set_data(self, index: QModelIndex, value, role: int = ...) -> bool:
            event = index.data(self.EVENT)
            try:
                event.value = value
            except Exception as exc:
                logging.exception(exc)
                return False
            else:
                self.dataChanged.emit(index, index)  # type: ignore
                return True
    

    When I try to enter a new value in a cell's editor and press Enter, the new value doesn't appear in the cell. This occurs even if there are no exceptions.

    I am using a normal QTableView instance for this model. The data gets correctly displayed initially after loading.

    PySide: 6.4.2

    EDIT: Fixed it by adding this line before emitting dataChanged :

    self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole)
    
    JonBJ 1 Reply Last reply
    0
    • D demberto has marked this topic as solved on
    • D demberto
      class EventsTableModel(QStandardItemModel):
          EVENT = 1000
      
          def __init__(self, et: EventTree, show_only: list[EventEnum]) -> None:
              super().__init__(None)
              self.et = et
              self.events = tuple(et.get(*show_only))
              self.set_horizontal_header_labels(["ID", "Value"])
      
              for event in self.events:
                  id_item = QStandardItem(str(event.id))
                  id_item.set_editable(False)
                  val_item = QStandardItem()
                  val_item.set_data(event, self.EVENT)
      
                  try:
                      val_item.set_data(event.value, Qt.ItemDataRole.DisplayRole)
                  except NotImplementedError:
                      continue
                  self.append_row((id_item, val_item))
      
          def set_data(self, index: QModelIndex, value, role: int = ...) -> bool:
              event = index.data(self.EVENT)
              try:
                  event.value = value
              except Exception as exc:
                  logging.exception(exc)
                  return False
              else:
                  self.dataChanged.emit(index, index)  # type: ignore
                  return True
      

      When I try to enter a new value in a cell's editor and press Enter, the new value doesn't appear in the cell. This occurs even if there are no exceptions.

      I am using a normal QTableView instance for this model. The data gets correctly displayed initially after loading.

      PySide: 6.4.2

      EDIT: Fixed it by adding this line before emitting dataChanged :

      self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole)
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @demberto
      Your set_data() method does not use the role parameter passed to it, which it should, or you should not have it accept such a parameter.
      If you do make it use the parameter, you should be passing Qt.ItemDataRole.EditRole not DisplayRole.

      D 1 Reply Last reply
      0
      • JonBJ JonB

        @demberto
        Your set_data() method does not use the role parameter passed to it, which it should, or you should not have it accept such a parameter.
        If you do make it use the parameter, you should be passing Qt.ItemDataRole.EditRole not DisplayRole.

        D Offline
        D Offline
        demberto
        wrote on last edited by demberto
        #3

        @JonB Do you mean the place where I call self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole)?

        OR do you mean this?

        def set_data(self, index: QModelIndex, value, role: int = ...) -> bool:
                event = index.data(self.EVENT)
                try:
                    event.value = value
                except Exception as exc:
                    logging.exception(exc)
                    return False
                else:
                    self.item_from_index(index).set_data(value, role)
                    self.dataChanged.emit(index, index)  # type: ignore
                    return True
        

        EDIT: That works
        I still don't understand why I have to call self.item_from_index(index).set_data(value, role) explicitly. Isn't that what set_data mechanism is supposed to do internally, or I should call super-class set_data in my else clause?

        JonBJ 1 Reply Last reply
        0
        • D demberto

          @JonB Do you mean the place where I call self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole)?

          OR do you mean this?

          def set_data(self, index: QModelIndex, value, role: int = ...) -> bool:
                  event = index.data(self.EVENT)
                  try:
                      event.value = value
                  except Exception as exc:
                      logging.exception(exc)
                      return False
                  else:
                      self.item_from_index(index).set_data(value, role)
                      self.dataChanged.emit(index, index)  # type: ignore
                      return True
          

          EDIT: That works
          I still don't understand why I have to call self.item_from_index(index).set_data(value, role) explicitly. Isn't that what set_data mechanism is supposed to do internally, or I should call super-class set_data in my else clause?

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

          @demberto
          Yes, you should call base QStandardItemModel.setData() to handle the case you don't.

          Your code is bad for the normal, successful case. You do not return True, you just drop off the end of the method and Python will doubtless return None/False, could be a problem.

          The base setData() defaults role = EditRole for the parameter. You really ought do so too.

          Where you call it you show self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole). That should really be EditRole, or you can omit it if you change to default as per previous point.

          D 1 Reply Last reply
          1
          • JonBJ JonB

            @demberto
            Yes, you should call base QStandardItemModel.setData() to handle the case you don't.

            Your code is bad for the normal, successful case. You do not return True, you just drop off the end of the method and Python will doubtless return None/False, could be a problem.

            The base setData() defaults role = EditRole for the parameter. You really ought do so too.

            Where you call it you show self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole). That should really be EditRole, or you can omit it if you change to default as per previous point.

            D Offline
            D Offline
            demberto
            wrote on last edited by
            #5

            @JonB Finally:

            Your code is bad for the normal, successful case. You do not return True, you just drop off the end of the method and Python will doubtless return None/False, could be a problem.

            def set_data(self, index: QModelIndex, value, role: int = Qt.ItemDataRole.EditRole) -> bool:
                    event = index.data(self.EVENT)
                    try:
                        event.value = value
                    except Exception as exc:
                        logging.exception(exc)
                        return False
                    else:
                        super().set_data(index, value, role)
                    return True
            

            Thanks!

            JonBJ 1 Reply Last reply
            1
            • D demberto

              @JonB Finally:

              Your code is bad for the normal, successful case. You do not return True, you just drop off the end of the method and Python will doubtless return None/False, could be a problem.

              def set_data(self, index: QModelIndex, value, role: int = Qt.ItemDataRole.EditRole) -> bool:
                      event = index.data(self.EVENT)
                      try:
                          event.value = value
                      except Exception as exc:
                          logging.exception(exc)
                          return False
                      else:
                          super().set_data(index, value, role)
                      return True
              

              Thanks!

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

              @demberto
              No need for else: IMHO :) Now you hide if the base class setData() were to fail. To me

              return super().set_data(index, value, role)
              

              as the final line makes sense.

              1 Reply Last reply
              2

              • Login

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