Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. TableView seems to ignore dataChanged from QAbstractTableModel
Forum Updated to NodeBB v4.3 + New Features

TableView seems to ignore dataChanged from QAbstractTableModel

Scheduled Pinned Locked Moved Solved QML and Qt Quick
9 Posts 4 Posters 757 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
    j255
    wrote on last edited by
    #1

    Hello,

    I'm having trouble getting a TableView to update it's display when a QAbstractTableModel emits dataChanged.
    The intial data appears but then never updates in response to the dataChanged signal.

    The same QAbstractTableModel works fine in a separate Qt Widget application.

    The table model has a timer that modifies the model and emits dataChanged.
    The signal is definitely being emitted. I was able to connect to it from QML even but the view does not seem to update.

    Any ideas?

    Thanks,
    Jonah

    import QtQuick
    import QtQuick.Controls
    
    Window {
        visible: true
        width: 512
        height: 300
    
        TableView {
            id: tableView
            anchors.fill: parent
            model: MyTableModel{
                id: myModel
            }
    
            delegate: Rectangle{
                id: cell
                required property var model
                Text {
                    text: parent.model.display
                }
            }
    
            Connections {
                target: tableView.model
                onDataChanged: {
                    console.log(myModel.toString());
                }
            }
        }
    }
    
    
    
    J B 2 Replies Last reply
    0
    • J j255

      Ok, well it looks like views don't like dataChanged signals for ranges. I was emitting:

      emit dataChanged(index(0,0), index(0, 5), {Qt::DisplayRole, Qt::EditRole} );
      

      but if I limit it to a single column:

      emit dataChanged(index(0,2), index(0, 2), {Qt::DisplayRole, Qt::EditRole} );
      

      then the view reflects the change in that column!!

      I'm curious why this is the case. I'll have to dig around in the source. Since I don't see dataChanged in the source for the tableView. It must be in a higher level class. The dataChanged connection in TreeView seemed to be unrelated to display data.

      @Bob64 Yea I'm brand new to QML and I don't understand much of it yet. I was kind of trying different bits from different docs and examples. It did work without the property and just doing text: display.

      The following article seems to suggest there is a benefit to have a required property:
      https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html

      So I'm using this now:

      
          component MyDelegate : Rectangle {
              required property string display
              Text {
                  text: display
              }
          }
      
          TableView {
              id: tableView
              anchors.fill: parent
              model: MyTableModel{
                  id: myModel
              }
      
              delegate: MyDelegate {}
      
              Connections {
                  target: tableView.model
                  onDataChanged: {
                      console.log(myModel.toString());
                  }
      
              }
          }
      

      One other thing that caught me off guard was that.

      This wasn't sufficient:

              model: MyTableModel
      

      I needed at least this:

              model: MyTableModel {}
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #6

      @j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:

      Ok, well it looks like views don't like dataChanged signals for ranges

      I have never used QML, but I would be "surprised" if this is the case. Googling I see no evidence of anyone else reporting this. Are you 100% sure your range is valid? And you do have a data change in an existing row, this is not an insert of a row? Just to check, have you implemented setData() in the model and that is what is emitting the dataChanged() signal?

      J 1 Reply Last reply
      2
      • J j255

        Hello,

        I'm having trouble getting a TableView to update it's display when a QAbstractTableModel emits dataChanged.
        The intial data appears but then never updates in response to the dataChanged signal.

        The same QAbstractTableModel works fine in a separate Qt Widget application.

        The table model has a timer that modifies the model and emits dataChanged.
        The signal is definitely being emitted. I was able to connect to it from QML even but the view does not seem to update.

        Any ideas?

        Thanks,
        Jonah

        import QtQuick
        import QtQuick.Controls
        
        Window {
            visible: true
            width: 512
            height: 300
        
            TableView {
                id: tableView
                anchors.fill: parent
                model: MyTableModel{
                    id: myModel
                }
        
                delegate: Rectangle{
                    id: cell
                    required property var model
                    Text {
                        text: parent.model.display
                    }
                }
        
                Connections {
                    target: tableView.model
                    onDataChanged: {
                        console.log(myModel.toString());
                    }
                }
            }
        }
        
        
        
        J Offline
        J Offline
        j255
        wrote on last edited by
        #2

        Glancing at the source it doesn't look like the QML TableView connects to dataChanged while the QML Tree View does. The TableView seems to favor some other interfaces over the QAbstractTableModel. Maybe I can get an idea from that or maybe I'll try the TreeView.

        GrecKoG 1 Reply Last reply
        0
        • J j255

          Glancing at the source it doesn't look like the QML TableView connects to dataChanged while the QML Tree View does. The TableView seems to favor some other interfaces over the QAbstractTableModel. Maybe I can get an idea from that or maybe I'll try the TreeView.

          GrecKoG Offline
          GrecKoG Offline
          GrecKo
          Qt Champions 2018
          wrote on last edited by
          #3

          TableView does use dataChanged. Something else must be wrong on your end.

          1 Reply Last reply
          4
          • J j255

            Hello,

            I'm having trouble getting a TableView to update it's display when a QAbstractTableModel emits dataChanged.
            The intial data appears but then never updates in response to the dataChanged signal.

            The same QAbstractTableModel works fine in a separate Qt Widget application.

            The table model has a timer that modifies the model and emits dataChanged.
            The signal is definitely being emitted. I was able to connect to it from QML even but the view does not seem to update.

            Any ideas?

            Thanks,
            Jonah

            import QtQuick
            import QtQuick.Controls
            
            Window {
                visible: true
                width: 512
                height: 300
            
                TableView {
                    id: tableView
                    anchors.fill: parent
                    model: MyTableModel{
                        id: myModel
                    }
            
                    delegate: Rectangle{
                        id: cell
                        required property var model
                        Text {
                            text: parent.model.display
                        }
                    }
            
                    Connections {
                        target: tableView.model
                        onDataChanged: {
                            console.log(myModel.toString());
                        }
                    }
                }
            }
            
            
            
            B Offline
            B Offline
            Bob64
            wrote on last edited by
            #4

            @j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:

                delegate: Rectangle{
                    id: cell
                    required property var model
                    Text {
                        text: parent.model.display
                    }
                }
            

            Not an expert here, but I'm just trying to understand your delegate. What is the required property for? Also, if display is a role exposed on your model, you should just be able to access it directly in the delegate: text: display.

            I don't know if these things are actually related to any of the problems you see but they do look a bit unusual to me at least.

            J GrecKoG 2 Replies Last reply
            1
            • B Bob64

              @j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:

                  delegate: Rectangle{
                      id: cell
                      required property var model
                      Text {
                          text: parent.model.display
                      }
                  }
              

              Not an expert here, but I'm just trying to understand your delegate. What is the required property for? Also, if display is a role exposed on your model, you should just be able to access it directly in the delegate: text: display.

              I don't know if these things are actually related to any of the problems you see but they do look a bit unusual to me at least.

              J Offline
              J Offline
              j255
              wrote on last edited by j255
              #5

              Ok, well it looks like views don't like dataChanged signals for ranges. I was emitting:

              emit dataChanged(index(0,0), index(0, 5), {Qt::DisplayRole, Qt::EditRole} );
              

              but if I limit it to a single column:

              emit dataChanged(index(0,2), index(0, 2), {Qt::DisplayRole, Qt::EditRole} );
              

              then the view reflects the change in that column!!

              I'm curious why this is the case. I'll have to dig around in the source. Since I don't see dataChanged in the source for the tableView. It must be in a higher level class. The dataChanged connection in TreeView seemed to be unrelated to display data.

              @Bob64 Yea I'm brand new to QML and I don't understand much of it yet. I was kind of trying different bits from different docs and examples. It did work without the property and just doing text: display.

              The following article seems to suggest there is a benefit to have a required property:
              https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html

              So I'm using this now:

              
                  component MyDelegate : Rectangle {
                      required property string display
                      Text {
                          text: display
                      }
                  }
              
                  TableView {
                      id: tableView
                      anchors.fill: parent
                      model: MyTableModel{
                          id: myModel
                      }
              
                      delegate: MyDelegate {}
              
                      Connections {
                          target: tableView.model
                          onDataChanged: {
                              console.log(myModel.toString());
                          }
              
                      }
                  }
              

              One other thing that caught me off guard was that.

              This wasn't sufficient:

                      model: MyTableModel
              

              I needed at least this:

                      model: MyTableModel {}
              
              JonBJ 1 Reply Last reply
              1
              • J j255

                Ok, well it looks like views don't like dataChanged signals for ranges. I was emitting:

                emit dataChanged(index(0,0), index(0, 5), {Qt::DisplayRole, Qt::EditRole} );
                

                but if I limit it to a single column:

                emit dataChanged(index(0,2), index(0, 2), {Qt::DisplayRole, Qt::EditRole} );
                

                then the view reflects the change in that column!!

                I'm curious why this is the case. I'll have to dig around in the source. Since I don't see dataChanged in the source for the tableView. It must be in a higher level class. The dataChanged connection in TreeView seemed to be unrelated to display data.

                @Bob64 Yea I'm brand new to QML and I don't understand much of it yet. I was kind of trying different bits from different docs and examples. It did work without the property and just doing text: display.

                The following article seems to suggest there is a benefit to have a required property:
                https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html

                So I'm using this now:

                
                    component MyDelegate : Rectangle {
                        required property string display
                        Text {
                            text: display
                        }
                    }
                
                    TableView {
                        id: tableView
                        anchors.fill: parent
                        model: MyTableModel{
                            id: myModel
                        }
                
                        delegate: MyDelegate {}
                
                        Connections {
                            target: tableView.model
                            onDataChanged: {
                                console.log(myModel.toString());
                            }
                
                        }
                    }
                

                One other thing that caught me off guard was that.

                This wasn't sufficient:

                        model: MyTableModel
                

                I needed at least this:

                        model: MyTableModel {}
                
                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #6

                @j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:

                Ok, well it looks like views don't like dataChanged signals for ranges

                I have never used QML, but I would be "surprised" if this is the case. Googling I see no evidence of anyone else reporting this. Are you 100% sure your range is valid? And you do have a data change in an existing row, this is not an insert of a row? Just to check, have you implemented setData() in the model and that is what is emitting the dataChanged() signal?

                J 1 Reply Last reply
                2
                • B Bob64

                  @j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:

                      delegate: Rectangle{
                          id: cell
                          required property var model
                          Text {
                              text: parent.model.display
                          }
                      }
                  

                  Not an expert here, but I'm just trying to understand your delegate. What is the required property for? Also, if display is a role exposed on your model, you should just be able to access it directly in the delegate: text: display.

                  I don't know if these things are actually related to any of the problems you see but they do look a bit unusual to me at least.

                  GrecKoG Offline
                  GrecKoG Offline
                  GrecKo
                  Qt Champions 2018
                  wrote on last edited by
                  #7

                  @Bob64

                  using required properties is the recommended way to access model roles now : https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#models

                  context properties like you suggested should be avoided.

                  I also agree with @JonB that there is something fishy here. dataChanged with ranges is supported. Implementing setData or not is irrelevant though, given that dataChanged is correctly emitted.

                  B 1 Reply Last reply
                  4
                  • GrecKoG GrecKo

                    @Bob64

                    using required properties is the recommended way to access model roles now : https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#models

                    context properties like you suggested should be avoided.

                    I also agree with @JonB that there is something fishy here. dataChanged with ranges is supported. Implementing setData or not is irrelevant though, given that dataChanged is correctly emitted.

                    B Offline
                    B Offline
                    Bob64
                    wrote on last edited by
                    #8

                    @GrecKo yes, thank you - I have learned something today. I am still using Qt 5 and this doesn't seem to be emphasised as much in the docs there.

                    Having said that, OP was declaring model as a required property. My understanding now is that one should declare the roles that are being used. Is that correct?

                    1 Reply Last reply
                    1
                    • JonBJ JonB

                      @j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:

                      Ok, well it looks like views don't like dataChanged signals for ranges

                      I have never used QML, but I would be "surprised" if this is the case. Googling I see no evidence of anyone else reporting this. Are you 100% sure your range is valid? And you do have a data change in an existing row, this is not an insert of a row? Just to check, have you implemented setData() in the model and that is what is emitting the dataChanged() signal?

                      J Offline
                      J Offline
                      j255
                      wrote on last edited by j255
                      #9

                      @JonB Oh yea, you're right looks like my upper column was off by 1. The widget QTableView didn't seem to be phased by it. Thanks!

                      1 Reply Last reply
                      1
                      • J j255 has marked this topic as solved on

                      • Login

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