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. MouseArea works incorrectly inside TableView's delegate
QtWS25 Last Chance

MouseArea works incorrectly inside TableView's delegate

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
tableview
20 Posts 3 Posters 2.8k 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
    Dmitriano
    wrote on last edited by Dmitriano
    #1

    I wrote a sample application displaying cryptocurrency market data with TableView:

        TableView {
            id: table
            anchors.fill: parent
            columnSpacing: 1
            rowSpacing: 3
            clip: true
    
            property var columnWidths: [100, 90, 90, 60, 60];
            columnWidthProvider: function (column) { return columnWidths[column] }
    
            delegate: DelegateChooser {
                role: "type"
                DelegateChoice {
                    roleValue: "pair"
                    delegate: Rectangle
                    {
                        color: ma.containsMouse ? "#d2cc01" : "white"
                        Text
                        {
                            anchors.fill: parent
                            text: "%1 / %2".arg(model.item.base).arg(model.item.quote)
                        }
                        MouseArea
                        {
                            id: ma
                            anchors.fill: parent
                            hoverEnabled: true
                            onClicked: {
                                var url = ExchangeUrlTemplates[model.item.exchangeId].arg(model.item.base).arg(model.item.quote)
                                Qt.openUrlExternally(url)
                                console.log(url)
                            }
                        }
                    }
                }
                ...
    

    But got a bit glitching result, see the video: https://youtu.be/IoZtbtBUuYc

    The model calls beginMoveRows/endMoveRows when some real-time parameter is changed and TableView displays and sorts its rows correctly, but MouseArea randomly stays in hover state and mouse clicks are triggered on wrong rows (and a wrong URL is opened in the browser).

    My QT version is 15.0, OS: Windows 10

    1 Reply Last reply
    0
    • jeremy_kJ Offline
      jeremy_kJ Offline
      jeremy_k
      wrote on last edited by
      #2

      Is the row height defined somewhere? If not, it looks like TableView will use the height of Rectangle, which is probably 0.

      Asking a question about code? http://eel.is/iso-c++/testcase/

      D 1 Reply Last reply
      0
      • jeremy_kJ jeremy_k

        Is the row height defined somewhere? If not, it looks like TableView will use the height of Rectangle, which is probably 0.

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

        @jeremy_k I tried to define height and width of the Rectangle explicitly:

            TableView {
                id: table
                anchors.fill: parent
                columnSpacing: 1
                rowSpacing: 3
                clip: true
        
                property var columnWidths: [100, 90, 90, 60, 60];
                columnWidthProvider: function (column) { return columnWidths[column] }
        
                delegate: DelegateChooser {
                    role: "type"
                    DelegateChoice {
                        roleValue: "pair"
                        delegate: Rectangle
                        {
                            height: 20
                            width: 100
                            color: ma.containsMouse ? "#d2cc01" : "white"
                            Text
                            {
                                anchors.fill: parent
                                text: "%1 / %2".arg(model.item.base).arg(model.item.quote)
                            }
                            MouseArea
                            {
                                id: ma
                                anchors.fill: parent
                                hoverEnabled: true
                                onClicked: {
                                    var url = ExchangeUrlTemplates[model.item.exchangeId].arg(model.item.base).arg(model.item.quote)
                                    Qt.openUrlExternally(url)
                                    console.log(url)
                                }
                            }
                        }
                    }
        

        but this did not help.

        When the model is not sorted in real-time MouseArea works correctly and I would say I works nicely, see another video: https://youtu.be/Akh09FZ80Kc

        jeremy_kJ 1 Reply Last reply
        0
        • D Dmitriano

          @jeremy_k I tried to define height and width of the Rectangle explicitly:

              TableView {
                  id: table
                  anchors.fill: parent
                  columnSpacing: 1
                  rowSpacing: 3
                  clip: true
          
                  property var columnWidths: [100, 90, 90, 60, 60];
                  columnWidthProvider: function (column) { return columnWidths[column] }
          
                  delegate: DelegateChooser {
                      role: "type"
                      DelegateChoice {
                          roleValue: "pair"
                          delegate: Rectangle
                          {
                              height: 20
                              width: 100
                              color: ma.containsMouse ? "#d2cc01" : "white"
                              Text
                              {
                                  anchors.fill: parent
                                  text: "%1 / %2".arg(model.item.base).arg(model.item.quote)
                              }
                              MouseArea
                              {
                                  id: ma
                                  anchors.fill: parent
                                  hoverEnabled: true
                                  onClicked: {
                                      var url = ExchangeUrlTemplates[model.item.exchangeId].arg(model.item.base).arg(model.item.quote)
                                      Qt.openUrlExternally(url)
                                      console.log(url)
                                  }
                              }
                          }
                      }
          

          but this did not help.

          When the model is not sorted in real-time MouseArea works correctly and I would say I works nicely, see another video: https://youtu.be/Akh09FZ80Kc

          jeremy_kJ Offline
          jeremy_kJ Offline
          jeremy_k
          wrote on last edited by
          #4

          In retrospect, I see the first video demonstrated that the Rectangle height wasn't 0. The color change was visible even if it was misbehaving.

          Given that the view behaves minus the sorting, how does that work? Does it do the same thing with a simpler view? eg:

          ListView {
              model: ...
              delegate: Text {
                  text: model.item.base + ma.containsMouse ? " *" : ""
                  MouseArea {
                      id: ma
                      anchors.fill: parent
                      hoverEnabled: true
                  }
              }
          }
          

          Asking a question about code? http://eel.is/iso-c++/testcase/

          D 1 Reply Last reply
          0
          • fcarneyF Offline
            fcarneyF Offline
            fcarney
            wrote on last edited by
            #5

            If it doesn't match the view on sort then maybe a signal is not being called in the model. Is this a custom model? Have you tested the model with: QAbstractItemModelTester?

            C++ is a perfectly valid school of magic.

            D 1 Reply Last reply
            0
            • jeremy_kJ Offline
              jeremy_kJ Offline
              jeremy_k
              wrote on last edited by
              #6

              I have an idea of what's happening, although some of the details are still fuzzy.
              Sorry about the large example. Move the cursor to the box in the left side displaying "0->1". This middle row should turn yellow. Click and it should change to "1->2". Click again and it goes back to 0->1. The pseudo-highlight does some interesting things.

              import QtQuick 2.15
              import QtQuick.Window 2.15
              
              Window {
                  width: 640
                  height: 480
                  visible: true
              
                  ListModel {
                      id: lm
                      ListElement { data: 0 }
                      ListElement { data: 1 }
                      ListElement { data: 2 }
                  }
              
                  ListView {
                      anchors.fill: parent
                      model: lm
                      delegate: Rectangle {
                          width: ListView.view.width
                          height: 30
                          color: ma.containsMouse ? "yellow" : "white"
                          MouseArea {
                              id: ma
                              anchors.fill: parent
                              hoverEnabled: true
                              onContainsMouseChanged: print("containsMouse", containsMouse, model.data)
                          }
                          Text {
                              anchors.centerIn: parent
                              text: model.data
                          }
                      }
                  }
              
                  Rectangle {
                      id: button
                      width: 100
                      height: 30
                      y: 30
                      border.width: 1
                      border.color: "black"
                      property int moveStart
                      Text {
                          anchors.centerIn: parent
                          text: button.moveStart + "->" + (button.moveStart + 1)
                      }
                      MouseArea {
                          anchors.fill: parent
                          onClicked: button.moveStart == 0 ? button.moveStart = 1 : button.moveStart = 0
                      }
                  }
              
                  Timer {
                      interval: 1000
                      onTriggered: lm.move(button.moveStart, button.moveStart + 1, 1)
                      running: true
                      repeat: true
                  }
              }
              

              Under some circumstances, the model and view being reordered doesn't cause the the MouseArea to detect that it no longer contains the cursor, which results in the pseudo-highlight remaining with the item as it moves around the view. In other circumstances, the MouseArea does detect, which results in the flicker of the highlight from the old item to the new. One of these two is likely a Qt bug. I'm not sure which.

              Ignoring the potential framework defect:

              • How does the user reliably select an item if it frequently changes position?
              • If the user does successfully select, is the highlight supposed to stay with the item when it moves, or jump to the new item under the cursor?

              Making the selection click-based rather than hover-based solves the second problem. The first problem remains, unless the interface is intentionally a game of chance.

              Asking a question about code? http://eel.is/iso-c++/testcase/

              D 2 Replies Last reply
              0
              • fcarneyF fcarney

                If it doesn't match the view on sort then maybe a signal is not being called in the model. Is this a custom model? Have you tested the model with: QAbstractItemModelTester?

                D Offline
                D Offline
                Dmitriano
                wrote on last edited by Dmitriano
                #7

                @fcarney To test my model with QAbstractItemModelTester I added the following code to my function getAllMarkets() that created the model:

                QObject * ExchangeListModel::getAllMarkets()
                {
                    //Creating the model p_table...
                
                    new QAbstractItemModelTester(p_table);
                
                    return p_table;
                }
                

                but I did not notice some messages in the application output.

                fcarneyF 1 Reply Last reply
                0
                • jeremy_kJ jeremy_k

                  In retrospect, I see the first video demonstrated that the Rectangle height wasn't 0. The color change was visible even if it was misbehaving.

                  Given that the view behaves minus the sorting, how does that work? Does it do the same thing with a simpler view? eg:

                  ListView {
                      model: ...
                      delegate: Text {
                          text: model.item.base + ma.containsMouse ? " *" : ""
                          MouseArea {
                              id: ma
                              anchors.fill: parent
                              hoverEnabled: true
                          }
                      }
                  }
                  
                  D Offline
                  D Offline
                  Dmitriano
                  wrote on last edited by Dmitriano
                  #8

                  @jeremy_k Basically your example with ListView works, see the video: https://youtu.be/NZW5jHFpAlU (but the star periodically jumps away
                  from the cursor a bit).

                  Item {
                      id: root
                      property alias model: list.model
                  
                      ListView {
                          id: list
                          anchors.fill: parent
                  
                          delegate: Text {
                              text: item.base + (ma.containsMouse ? " *" : "")
                              MouseArea {
                                  id: ma
                                  anchors.fill: parent
                                  hoverEnabled: true
                              }
                          }
                      }
                  }
                  

                  note that I use not model.item.base but item.base.

                  But when I use the same delegate with my TableView the star jumps randomly between the cells, see https://youtu.be/3Br8jsX7f-E

                  Item {
                      id: root
                      property alias model: table.model
                  
                      TableView {
                          id: table
                          anchors.fill: parent
                          columnSpacing: 1
                          rowSpacing: 3
                          clip: true
                  
                          property var columnWidths: [100, 90, 90, 60, 60];
                          columnWidthProvider: function (column) { return columnWidths[column] }
                  
                          delegate: Text {
                              text: model.item.base + (ma.containsMouse ? " *" : "")
                              MouseArea {
                                  id: ma
                                  anchors.fill: parent
                                  hoverEnabled: true
                              }
                          }
                      }
                  }
                  
                  1 Reply Last reply
                  0
                  • jeremy_kJ jeremy_k

                    I have an idea of what's happening, although some of the details are still fuzzy.
                    Sorry about the large example. Move the cursor to the box in the left side displaying "0->1". This middle row should turn yellow. Click and it should change to "1->2". Click again and it goes back to 0->1. The pseudo-highlight does some interesting things.

                    import QtQuick 2.15
                    import QtQuick.Window 2.15
                    
                    Window {
                        width: 640
                        height: 480
                        visible: true
                    
                        ListModel {
                            id: lm
                            ListElement { data: 0 }
                            ListElement { data: 1 }
                            ListElement { data: 2 }
                        }
                    
                        ListView {
                            anchors.fill: parent
                            model: lm
                            delegate: Rectangle {
                                width: ListView.view.width
                                height: 30
                                color: ma.containsMouse ? "yellow" : "white"
                                MouseArea {
                                    id: ma
                                    anchors.fill: parent
                                    hoverEnabled: true
                                    onContainsMouseChanged: print("containsMouse", containsMouse, model.data)
                                }
                                Text {
                                    anchors.centerIn: parent
                                    text: model.data
                                }
                            }
                        }
                    
                        Rectangle {
                            id: button
                            width: 100
                            height: 30
                            y: 30
                            border.width: 1
                            border.color: "black"
                            property int moveStart
                            Text {
                                anchors.centerIn: parent
                                text: button.moveStart + "->" + (button.moveStart + 1)
                            }
                            MouseArea {
                                anchors.fill: parent
                                onClicked: button.moveStart == 0 ? button.moveStart = 1 : button.moveStart = 0
                            }
                        }
                    
                        Timer {
                            interval: 1000
                            onTriggered: lm.move(button.moveStart, button.moveStart + 1, 1)
                            running: true
                            repeat: true
                        }
                    }
                    

                    Under some circumstances, the model and view being reordered doesn't cause the the MouseArea to detect that it no longer contains the cursor, which results in the pseudo-highlight remaining with the item as it moves around the view. In other circumstances, the MouseArea does detect, which results in the flicker of the highlight from the old item to the new. One of these two is likely a Qt bug. I'm not sure which.

                    Ignoring the potential framework defect:

                    • How does the user reliably select an item if it frequently changes position?
                    • If the user does successfully select, is the highlight supposed to stay with the item when it moves, or jump to the new item under the cursor?

                    Making the selection click-based rather than hover-based solves the second problem. The first problem remains, unless the interface is intentionally a game of chance.

                    D Offline
                    D Offline
                    Dmitriano
                    wrote on last edited by
                    #9

                    @jeremy_k As I mentioned in my first post, the clicks are also handled incorrectly. (A wrong url is opened in the browser.)

                    1 Reply Last reply
                    0
                    • jeremy_kJ jeremy_k

                      I have an idea of what's happening, although some of the details are still fuzzy.
                      Sorry about the large example. Move the cursor to the box in the left side displaying "0->1". This middle row should turn yellow. Click and it should change to "1->2". Click again and it goes back to 0->1. The pseudo-highlight does some interesting things.

                      import QtQuick 2.15
                      import QtQuick.Window 2.15
                      
                      Window {
                          width: 640
                          height: 480
                          visible: true
                      
                          ListModel {
                              id: lm
                              ListElement { data: 0 }
                              ListElement { data: 1 }
                              ListElement { data: 2 }
                          }
                      
                          ListView {
                              anchors.fill: parent
                              model: lm
                              delegate: Rectangle {
                                  width: ListView.view.width
                                  height: 30
                                  color: ma.containsMouse ? "yellow" : "white"
                                  MouseArea {
                                      id: ma
                                      anchors.fill: parent
                                      hoverEnabled: true
                                      onContainsMouseChanged: print("containsMouse", containsMouse, model.data)
                                  }
                                  Text {
                                      anchors.centerIn: parent
                                      text: model.data
                                  }
                              }
                          }
                      
                          Rectangle {
                              id: button
                              width: 100
                              height: 30
                              y: 30
                              border.width: 1
                              border.color: "black"
                              property int moveStart
                              Text {
                                  anchors.centerIn: parent
                                  text: button.moveStart + "->" + (button.moveStart + 1)
                              }
                              MouseArea {
                                  anchors.fill: parent
                                  onClicked: button.moveStart == 0 ? button.moveStart = 1 : button.moveStart = 0
                              }
                          }
                      
                          Timer {
                              interval: 1000
                              onTriggered: lm.move(button.moveStart, button.moveStart + 1, 1)
                              running: true
                              repeat: true
                          }
                      }
                      

                      Under some circumstances, the model and view being reordered doesn't cause the the MouseArea to detect that it no longer contains the cursor, which results in the pseudo-highlight remaining with the item as it moves around the view. In other circumstances, the MouseArea does detect, which results in the flicker of the highlight from the old item to the new. One of these two is likely a Qt bug. I'm not sure which.

                      Ignoring the potential framework defect:

                      • How does the user reliably select an item if it frequently changes position?
                      • If the user does successfully select, is the highlight supposed to stay with the item when it moves, or jump to the new item under the cursor?

                      Making the selection click-based rather than hover-based solves the second problem. The first problem remains, unless the interface is intentionally a game of chance.

                      D Offline
                      D Offline
                      Dmitriano
                      wrote on last edited by Dmitriano
                      #10

                      @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                      How does the user reliably select an item if it frequently changes position?
                      If the user does successfully select, is the highlight supposed to stay with the item when it moves, or jump to the new item under the cursor?

                      1. The user attempts to select the item he sees at he moment and if an attempt was unsuccessful, he retries. Or the user presses 'Freeze' button that stops sorting and selects an item from the static list. Or, theoretically, the update frequency can be configured somehow.

                      2. If the user does successfully select the item some page are added to a StackView above the TableView (and TableView becomes invisible), so the highlight disappares.

                      And I mentioned in my first post, the clicks are also handled incorrectly. (A wrong url is opened in the browser.)

                      So is this a TableView's bug? Should it be reported?

                      jeremy_kJ 1 Reply Last reply
                      0
                      • D Dmitriano

                        @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                        How does the user reliably select an item if it frequently changes position?
                        If the user does successfully select, is the highlight supposed to stay with the item when it moves, or jump to the new item under the cursor?

                        1. The user attempts to select the item he sees at he moment and if an attempt was unsuccessful, he retries. Or the user presses 'Freeze' button that stops sorting and selects an item from the static list. Or, theoretically, the update frequency can be configured somehow.

                        2. If the user does successfully select the item some page are added to a StackView above the TableView (and TableView becomes invisible), so the highlight disappares.

                        And I mentioned in my first post, the clicks are also handled incorrectly. (A wrong url is opened in the browser.)

                        So is this a TableView's bug? Should it be reported?

                        jeremy_kJ Offline
                        jeremy_kJ Offline
                        jeremy_k
                        wrote on last edited by
                        #11

                        @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                        @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                        How does the user reliably select an item if it frequently changes position?
                        If the user does successfully select, is the highlight supposed to stay with the item when it moves, or jump to the new item under the cursor?

                        1. The user attempts to select the item he sees at he moment and if an attempt was unsuccessful, he retries. Or the user presses 'Freeze' button that stops sorting and selects an item from the static list. Or, theoretically, the update frequency can be configured somehow.

                        For some reason this reminds me of a claw crane.

                        1. If the user does successfully select the item some page are added to a StackView above the TableView (and TableView becomes invisible), so the highlight disappares.

                        And I mentioned in my first post, the clicks are also handled incorrectly. (A wrong url is opened in the browser.)

                        The MouseArea might be grabbing the mouse, in which case it will also receive the press and release events.

                        So is this a TableView's bug? Should it be reported?

                        I'm leaning toward the MouseArea being responsible, whether a bug or misuse. You didn't mention which TableView this is using. The Qt Quick Controls 1 version has a few signals for handling user selection. The TableView in QtQuick starting from 5.12 doesn't seem to have as rich of an API, but perhaps the UI can be implemented with a single stationary MouseArea that covers the entire view and finds the correct delegate with Item.childAt(), and the Flickable.contentItem.

                        Asking a question about code? http://eel.is/iso-c++/testcase/

                        D 1 Reply Last reply
                        0
                        • jeremy_kJ jeremy_k

                          @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                          @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                          How does the user reliably select an item if it frequently changes position?
                          If the user does successfully select, is the highlight supposed to stay with the item when it moves, or jump to the new item under the cursor?

                          1. The user attempts to select the item he sees at he moment and if an attempt was unsuccessful, he retries. Or the user presses 'Freeze' button that stops sorting and selects an item from the static list. Or, theoretically, the update frequency can be configured somehow.

                          For some reason this reminds me of a claw crane.

                          1. If the user does successfully select the item some page are added to a StackView above the TableView (and TableView becomes invisible), so the highlight disappares.

                          And I mentioned in my first post, the clicks are also handled incorrectly. (A wrong url is opened in the browser.)

                          The MouseArea might be grabbing the mouse, in which case it will also receive the press and release events.

                          So is this a TableView's bug? Should it be reported?

                          I'm leaning toward the MouseArea being responsible, whether a bug or misuse. You didn't mention which TableView this is using. The Qt Quick Controls 1 version has a few signals for handling user selection. The TableView in QtQuick starting from 5.12 doesn't seem to have as rich of an API, but perhaps the UI can be implemented with a single stationary MouseArea that covers the entire view and finds the correct delegate with Item.childAt(), and the Flickable.contentItem.

                          D Offline
                          D Offline
                          Dmitriano
                          wrote on last edited by
                          #12

                          @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                          For some reason this reminds me of a claw crane.

                          Yes, it can be strange for some users, so theoretically, such kind of the uses will temporarily disable the sorting and then click on a row.

                          You didn't mention which TableView this is using.

                          I am using TableView 2.0

                          but perhaps the UI can be implemented with a single stationary MouseArea that covers the entire view and finds the correct delegate with Item.childAt(), and the Flickable.contentItem.

                          What Item.childAt() is? How to use it? Currently I use MouseArea in a similar way, see the code:

                              TableView {
                                  id: table
                          
                                  property var columnWidths: [100, 80, 80, 120];
                                  columnWidthProvider: function (column) { return columnWidths[column]; }
                          
                                  property var rowHeight: 40
                                  rowHeightProvider: function (column) { return rowHeight; }
                          
                                  MouseArea
                                  {
                                      id: ma
                                      anchors.fill: parent
                                      hoverEnabled: true
                                      onClicked: {
                                          var index = Math.floor(mouse.y / (table.rowHeight + table.rowSpacing));
                                          console.log(index, " ", mouse.x, " ", mouse.y, " ", table.contentX, " ", table.contentY)
                                          var item = table.model.rowKey(index)
                                          window.openMarket(item)
                                      }
                                  }
                          
                                  delegate: DelegateChooser {
                                      role: "type"
                                      DelegateChoice {
                                          roleValue: "symbol"
                                          delegate: SymbolCell { item: model.item }
                                      }
                                  }
                                  ...
                              }
                          

                          it works with a fixed row height that I define with rowHeight property.

                          jeremy_kJ 1 Reply Last reply
                          0
                          • D Dmitriano

                            @fcarney To test my model with QAbstractItemModelTester I added the following code to my function getAllMarkets() that created the model:

                            QObject * ExchangeListModel::getAllMarkets()
                            {
                                //Creating the model p_table...
                            
                                new QAbstractItemModelTester(p_table);
                            
                                return p_table;
                            }
                            

                            but I did not notice some messages in the application output.

                            fcarneyF Offline
                            fcarneyF Offline
                            fcarney
                            wrote on last edited by
                            #13

                            @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                            To test my model with QAbstractItemModelTester I added the following code to my function getAllMarkets() that created the model:

                            Put it in the constructor. Set it to warn so it doesn't kill the app on you.

                            C++ is a perfectly valid school of magic.

                            1 Reply Last reply
                            0
                            • D Dmitriano

                              @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                              For some reason this reminds me of a claw crane.

                              Yes, it can be strange for some users, so theoretically, such kind of the uses will temporarily disable the sorting and then click on a row.

                              You didn't mention which TableView this is using.

                              I am using TableView 2.0

                              but perhaps the UI can be implemented with a single stationary MouseArea that covers the entire view and finds the correct delegate with Item.childAt(), and the Flickable.contentItem.

                              What Item.childAt() is? How to use it? Currently I use MouseArea in a similar way, see the code:

                                  TableView {
                                      id: table
                              
                                      property var columnWidths: [100, 80, 80, 120];
                                      columnWidthProvider: function (column) { return columnWidths[column]; }
                              
                                      property var rowHeight: 40
                                      rowHeightProvider: function (column) { return rowHeight; }
                              
                                      MouseArea
                                      {
                                          id: ma
                                          anchors.fill: parent
                                          hoverEnabled: true
                                          onClicked: {
                                              var index = Math.floor(mouse.y / (table.rowHeight + table.rowSpacing));
                                              console.log(index, " ", mouse.x, " ", mouse.y, " ", table.contentX, " ", table.contentY)
                                              var item = table.model.rowKey(index)
                                              window.openMarket(item)
                                          }
                                      }
                              
                                      delegate: DelegateChooser {
                                          role: "type"
                                          DelegateChoice {
                                              roleValue: "symbol"
                                              delegate: SymbolCell { item: model.item }
                                          }
                                      }
                                      ...
                                  }
                              

                              it works with a fixed row height that I define with rowHeight property.

                              jeremy_kJ Offline
                              jeremy_kJ Offline
                              jeremy_k
                              wrote on last edited by
                              #14

                              @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                              @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                              but perhaps the UI can be implemented with a single stationary MouseArea that covers the entire view and finds the correct delegate with Item.childAt(), and the Flickable.contentItem.

                              What Item.childAt() is? How to use it? Currently I use MouseArea in a similar way, see the code:

                              https://doc.qt.io/qt-5/qml-qtquick-item.html#childAt-method

                              import QtQuick 2.15
                              import QtQuick.Window 2.15
                              
                              Window {
                                  width: 100
                                  height: 100
                                  visible: true
                              
                                  Flickable {
                                      id: flickable
                                      anchors.fill: parent
                                      Repeater {
                                          id: repeater
                                          model: 10
                                          delegate: Rectangle {
                                              border.color: "black"
                                              border.width: 1
                                              width: 20
                                              height: 20
                                              x: index * 40
                                              y: x
                                          }
                                      }
                                  }
                              
                                  Timer {
                                      interval: 1000
                                      running: true
                                      repeat: true
                                      onTriggered: {
                                          for (var index in flickable.contentItem.children) {
                                              var item = flickable.contentItem.children[index]
                                              item.x = Math.floor(Math.random() * flickable.contentItem.width);
                                              item.y = Math.floor(Math.random() * flickable.contentItem.height);
                                          }
                                          mouseArea.updateHighlight();
                                      }
                                  }
                              
                                  MouseArea {
                                      id: mouseArea
                                      anchors.fill: flickable
                                      hoverEnabled: true
                                      property Item lastItem: null
                              
                                      function updateHighlight() {
                                          var item = flickable.contentItem.childAt(mouseX + flickable.contentX, mouseY + flickable.contentY);
                                          if (item)
                                              item.color = "yellow";
                                          if (lastItem && item !== lastItem)
                                              lastItem.color = "white";
                                          lastItem = item;
                                      }
                              
                                      onPositionChanged: updateHighlight()
                                  }
                              }
                              
                              

                              Asking a question about code? http://eel.is/iso-c++/testcase/

                              D 1 Reply Last reply
                              0
                              • jeremy_kJ Offline
                                jeremy_kJ Offline
                                jeremy_k
                                wrote on last edited by
                                #15

                                Moving the MouseArea into the Repeater delegate and removing the timer's call to updateHighlight() in the above example also works as expected. This suggests that MouseArea is able to detect when a hover has ended due to the MouseArea moving, at least in this scenario.

                                Asking a question about code? http://eel.is/iso-c++/testcase/

                                1 Reply Last reply
                                0
                                • jeremy_kJ jeremy_k

                                  @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                                  @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                  but perhaps the UI can be implemented with a single stationary MouseArea that covers the entire view and finds the correct delegate with Item.childAt(), and the Flickable.contentItem.

                                  What Item.childAt() is? How to use it? Currently I use MouseArea in a similar way, see the code:

                                  https://doc.qt.io/qt-5/qml-qtquick-item.html#childAt-method

                                  import QtQuick 2.15
                                  import QtQuick.Window 2.15
                                  
                                  Window {
                                      width: 100
                                      height: 100
                                      visible: true
                                  
                                      Flickable {
                                          id: flickable
                                          anchors.fill: parent
                                          Repeater {
                                              id: repeater
                                              model: 10
                                              delegate: Rectangle {
                                                  border.color: "black"
                                                  border.width: 1
                                                  width: 20
                                                  height: 20
                                                  x: index * 40
                                                  y: x
                                              }
                                          }
                                      }
                                  
                                      Timer {
                                          interval: 1000
                                          running: true
                                          repeat: true
                                          onTriggered: {
                                              for (var index in flickable.contentItem.children) {
                                                  var item = flickable.contentItem.children[index]
                                                  item.x = Math.floor(Math.random() * flickable.contentItem.width);
                                                  item.y = Math.floor(Math.random() * flickable.contentItem.height);
                                              }
                                              mouseArea.updateHighlight();
                                          }
                                      }
                                  
                                      MouseArea {
                                          id: mouseArea
                                          anchors.fill: flickable
                                          hoverEnabled: true
                                          property Item lastItem: null
                                  
                                          function updateHighlight() {
                                              var item = flickable.contentItem.childAt(mouseX + flickable.contentX, mouseY + flickable.contentY);
                                              if (item)
                                                  item.color = "yellow";
                                              if (lastItem && item !== lastItem)
                                                  lastItem.color = "white";
                                              lastItem = item;
                                          }
                                  
                                          onPositionChanged: updateHighlight()
                                      }
                                  }
                                  
                                  
                                  D Offline
                                  D Offline
                                  Dmitriano
                                  wrote on last edited by Dmitriano
                                  #16

                                  @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                      function updateHighlight() {
                                          var item = flickable.contentItem.childAt(mouseX + flickable.contentX, mouseY + flickable.contentY);
                                  

                                  it is not clear what to do with the item accessed with the code above, because this item is a QML control like Text, for example, but I need not a QML control, but the model bound to the table row. I access it with

                                  var item = table.model.rowKey(index)
                                  

                                  where rowKey(index) is an invokable method explicitly defined in my model, so I need to know item's index.

                                  Also after doing some further testing, I noticed that CheckBox does not respond to clicks if the model is sorted dynamically, probably it uses MouseArea that stops working.

                                  jeremy_kJ 1 Reply Last reply
                                  0
                                  • D Dmitriano

                                    @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                        function updateHighlight() {
                                            var item = flickable.contentItem.childAt(mouseX + flickable.contentX, mouseY + flickable.contentY);
                                    

                                    it is not clear what to do with the item accessed with the code above, because this item is a QML control like Text, for example, but I need not a QML control, but the model bound to the table row. I access it with

                                    var item = table.model.rowKey(index)
                                    

                                    where rowKey(index) is an invokable method explicitly defined in my model, so I need to know item's index.

                                    Also after doing some further testing, I noticed that CheckBox does not respond to clicks if the model is sorted dynamically, probably it uses MouseArea that stops working.

                                    jeremy_kJ Offline
                                    jeremy_kJ Offline
                                    jeremy_k
                                    wrote on last edited by
                                    #17

                                    @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                                    @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                        function updateHighlight() {
                                            var item = flickable.contentItem.childAt(mouseX + flickable.contentX, mouseY + flickable.contentY);
                                    

                                    it is not clear what to do with the item accessed with the code above, because this item is a QML control like Text, for example, but I need not a QML control, but the model bound to the table row. I access it with

                                    var item = table.model.rowKey(index)
                                    

                                    where rowKey(index) is an invokable method explicitly defined in my model, so I need to know item's index.

                                    Use the properties of the item returned by childAt(). Color, index, etcetera.

                                    Asking a question about code? http://eel.is/iso-c++/testcase/

                                    D 1 Reply Last reply
                                    1
                                    • jeremy_kJ jeremy_k

                                      @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                                      @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                          function updateHighlight() {
                                              var item = flickable.contentItem.childAt(mouseX + flickable.contentX, mouseY + flickable.contentY);
                                      

                                      it is not clear what to do with the item accessed with the code above, because this item is a QML control like Text, for example, but I need not a QML control, but the model bound to the table row. I access it with

                                      var item = table.model.rowKey(index)
                                      

                                      where rowKey(index) is an invokable method explicitly defined in my model, so I need to know item's index.

                                      Use the properties of the item returned by childAt(). Color, index, etcetera.

                                      D Offline
                                      D Offline
                                      Dmitriano
                                      wrote on last edited by Dmitriano
                                      #18

                                      @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                      Use the properties of the item returned by childAt(). Color, index, etcetera.

                                      some of my items has item property that I declare explicitly with a code like (index and other properties can be defined in the same way)

                                              delegate: DelegateChooser {
                                                  role: "type"
                                                  DelegateChoice {
                                                      roleValue: "symbol"
                                                      delegate: SymbolCell { item: model.item }
                                                  }
                                      

                                      see the screenshot

                                      alt text

                                      so theoretically, my clicking code can be transformed into this:

                                              MouseArea
                                              {
                                                  id: ma
                                                  anchors.fill: parent
                                                  //hoverEnabled: true
                                                  onClicked:
                                                  {
                                                      var item = table.contentItem.childAt(mouse.x, mouse.y);
                                                      window.openMarket(item.item)
                                                  }
                                              }
                                      

                                      this also works with dynamically sorted model, but would require declaring item property explicitly in all the delegates that is a bit ugly overhead that prevents simple delegates (like a Text) from being simple.

                                      Also, as I mentioned above, CheckBox does not respond to clicks with dynamically sorted model and I did not try other interactive controls yet.

                                      And highlighting a row is still a task that we can't solve without an ugly overhead. For example, if the mouse is over an item (delegate) and I change its color I can't change it back when item's index is changed and the item is moved away.

                                      jeremy_kJ 1 Reply Last reply
                                      0
                                      • D Dmitriano

                                        @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                        Use the properties of the item returned by childAt(). Color, index, etcetera.

                                        some of my items has item property that I declare explicitly with a code like (index and other properties can be defined in the same way)

                                                delegate: DelegateChooser {
                                                    role: "type"
                                                    DelegateChoice {
                                                        roleValue: "symbol"
                                                        delegate: SymbolCell { item: model.item }
                                                    }
                                        

                                        see the screenshot

                                        alt text

                                        so theoretically, my clicking code can be transformed into this:

                                                MouseArea
                                                {
                                                    id: ma
                                                    anchors.fill: parent
                                                    //hoverEnabled: true
                                                    onClicked:
                                                    {
                                                        var item = table.contentItem.childAt(mouse.x, mouse.y);
                                                        window.openMarket(item.item)
                                                    }
                                                }
                                        

                                        this also works with dynamically sorted model, but would require declaring item property explicitly in all the delegates that is a bit ugly overhead that prevents simple delegates (like a Text) from being simple.

                                        Also, as I mentioned above, CheckBox does not respond to clicks with dynamically sorted model and I did not try other interactive controls yet.

                                        And highlighting a row is still a task that we can't solve without an ugly overhead. For example, if the mouse is over an item (delegate) and I change its color I can't change it back when item's index is changed and the item is moved away.

                                        jeremy_kJ Offline
                                        jeremy_kJ Offline
                                        jeremy_k
                                        wrote on last edited by
                                        #19

                                        @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                                        @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                        Use the properties of the item returned by childAt(). Color, index, etcetera.

                                        some of my items has item property that I declare explicitly with a code like (index and other properties can be defined in the same way)

                                                delegate: DelegateChooser {
                                                    role: "type"
                                                    DelegateChoice {
                                                        roleValue: "symbol"
                                                        delegate: SymbolCell { item: model.item }
                                                    }
                                        

                                        see the screenshot

                                        alt text

                                        so theoretically, my clicking code can be transformed into this:

                                                MouseArea
                                                {
                                                    id: ma
                                                    anchors.fill: parent
                                                    //hoverEnabled: true
                                                    onClicked:
                                                    {
                                                        var item = table.contentItem.childAt(mouse.x, mouse.y);
                                                        window.openMarket(item.item)
                                                    }
                                                }
                                        

                                        Be careful about validating that childAt() returned a usable item. The user may have clicked over blank space.

                                        this also works with dynamically sorted model, but would require declaring item property explicitly in all the delegates that is a bit ugly overhead that prevents simple delegates (like a Text) from being simple.

                                        Sure. This seems to be a view with some complication. Overlaying a MouseArea on the entire thing is avoiding one set of complications by selecting another.

                                        Also, as I mentioned above, CheckBox does not respond to clicks with dynamically sorted model and I did not try other interactive controls yet.

                                        If the CheckBox is in a delegate, setting
                                        propagateComposedEvents on the overlay MouseArea may help.

                                        And highlighting a row is still a task that we can't solve without an ugly overhead. For example, if the mouse is over an item (delegate) and I change its color I can't change it back when item's index is changed and the item is moved away.

                                        That's what the lastItem property in https://forum.qt.io/post/621263 is for. Store identifying information for the next update and undo the changes when lastItem != current item. Or have a property that points to the selected row and have all others use the default color.

                                        If you haven't already, have a look at ListView. The highlight delegate and currentIndex property might make more sense for this use. The QtQuick

                                        Asking a question about code? http://eel.is/iso-c++/testcase/

                                        D 1 Reply Last reply
                                        0
                                        • jeremy_kJ jeremy_k

                                          @Dmitriano said in MouseArea works incorrectly inside TableView's delegate:

                                          @jeremy_k said in MouseArea works incorrectly inside TableView's delegate:

                                          Use the properties of the item returned by childAt(). Color, index, etcetera.

                                          some of my items has item property that I declare explicitly with a code like (index and other properties can be defined in the same way)

                                                  delegate: DelegateChooser {
                                                      role: "type"
                                                      DelegateChoice {
                                                          roleValue: "symbol"
                                                          delegate: SymbolCell { item: model.item }
                                                      }
                                          

                                          see the screenshot

                                          alt text

                                          so theoretically, my clicking code can be transformed into this:

                                                  MouseArea
                                                  {
                                                      id: ma
                                                      anchors.fill: parent
                                                      //hoverEnabled: true
                                                      onClicked:
                                                      {
                                                          var item = table.contentItem.childAt(mouse.x, mouse.y);
                                                          window.openMarket(item.item)
                                                      }
                                                  }
                                          

                                          Be careful about validating that childAt() returned a usable item. The user may have clicked over blank space.

                                          this also works with dynamically sorted model, but would require declaring item property explicitly in all the delegates that is a bit ugly overhead that prevents simple delegates (like a Text) from being simple.

                                          Sure. This seems to be a view with some complication. Overlaying a MouseArea on the entire thing is avoiding one set of complications by selecting another.

                                          Also, as I mentioned above, CheckBox does not respond to clicks with dynamically sorted model and I did not try other interactive controls yet.

                                          If the CheckBox is in a delegate, setting
                                          propagateComposedEvents on the overlay MouseArea may help.

                                          And highlighting a row is still a task that we can't solve without an ugly overhead. For example, if the mouse is over an item (delegate) and I change its color I can't change it back when item's index is changed and the item is moved away.

                                          That's what the lastItem property in https://forum.qt.io/post/621263 is for. Store identifying information for the next update and undo the changes when lastItem != current item. Or have a property that points to the selected row and have all others use the default color.

                                          If you haven't already, have a look at ListView. The highlight delegate and currentIndex property might make more sense for this use. The QtQuick

                                          D Offline
                                          D Offline
                                          Dmitriano
                                          wrote on last edited by Dmitriano
                                          #20

                                          @jeremy_k Unfortunately, my MouseArea that covers the entire view and finds the delegate does not detect row insertion. For example on the picture below two rows surrounded with green were inserted (with beginInsertRows/endInsertRows) and MouseArea stopped responding to the clicks on the last two rows surrounded with red:

                                          alt text

                                          Below I provided the source code of the entire TableView as it is now in my project:

                                              TableView
                                              {
                                                  id: table
                                                  anchors.fill: parent
                                                  columnSpacing: 5
                                                  rowSpacing: 3
                                                  clip: true
                                          
                                                  property var columnWidths: [100, 80, 80, 20, 20, 20, 90, 90];
                                                  columnWidthProvider: function (column) { return columnWidths[column]; }
                                          
                                                  property var rowHeight: 40
                                          
                                                  rowHeightProvider: function (column) { return rowHeight; }
                                          
                                                  ScrollBar.horizontal: ScrollBar{}
                                                  ScrollBar.vertical: ScrollBar{}
                                                  ScrollIndicator.horizontal: ScrollIndicator { }
                                                  ScrollIndicator.vertical: ScrollIndicator { }
                                          
                                                  MouseArea
                                                  {
                                                      //id: ma
                                                      anchors.fill: parent
                                                      //hoverEnabled: true
                                                      onClicked:
                                                      {
                                                          var index = Math.floor((mouse.y - table.originY) / (table.rowHeight + table.rowSpacing));
                                                          console.log("index:", index, " mouse: (", mouse.x, "," , mouse.y, ") table.origin: (", table.originX, ",", table.originY + ") table.content: (", table.contentX, ",", table.contentY + ")")
                                                          var item = table.model.rowKey(index)
                                                          if (item)
                                                              window.openMarket(item)
                                                      }
                                                  }
                                          
                                                  QtObject
                                                  {
                                                      id: enumSymbols
                                                      property string spotAllowed: "S"
                                                      property string marginAllowed: "M"
                                                      property string isolatedMarginAllowed: "I"
                                                  }
                                          
                                                  delegate: DelegateChooser {
                                                      role: "type"
                                                      DelegateChoice {
                                                          roleValue: "symbol"
                                                          delegate: SymbolCell { item: model.item }
                                                      }
                                                      DelegateChoice {
                                                          roleValue: "price"
                                                          delegate: Text {
                                                              horizontalAlignment: Text.AlignRight
                                                              verticalAlignment: Text.AlignVCenter
                                                              text: { var val = model.item[model.name]; return val ? val.toFixed(model.item.pricePrecision) : ""; }
                                                          }
                                                      }
                                                      DelegateChoice {
                                                          roleValue: "signal"
                                                          delegate: Text {
                                                              horizontalAlignment: Text.AlignRight
                                                              verticalAlignment: Text.AlignVCenter
                                                              text: TimeFormat.ago(model.item.signalTime, timeMachine.now)
                                                              color: model.item.signalTime ? "black" : "gray"
                                                          }
                                                      }
                                                      DelegateChoice {
                                                          roleValue: "enum"
                                                          delegate: Text
                                                          {
                                                              horizontalAlignment: Text.AlignHCenter
                                                              verticalAlignment: Text.AlignVCenter
                                                              text: model.display ? enumSymbols[model.name] : ""
                                                              color: "#1e73cd"
                                                          }
                                                      }
                                                      DelegateChoice {
                                                          roleValue: "zparams"
                                                          delegate: Text
                                                          {
                                                              property var zparams: model.item[model.name]
                                                              horizontalAlignment: Text.AlignRight
                                                              verticalAlignment: Text.AlignVCenter
                                                              text: zparams ? "(%1, %2, %3)".arg(zparams.lag).arg(zparams.threshold.toFixed(2)).arg(zparams.influence.toFixed(2)) : qsTr("No")
                                                              color: zparams ? "black" : "gray"
                                                          }
                                                      }
                                                      DelegateChoice {
                                                          roleValue: "check"
                                                          delegate: CheckBox {
                                                              checked: model.item[model.name];
                                                              onClicked: {
                                                                  table.model.beginUpdateItem(model.item)
                                                                  model.item[model.name] = checked
                                                                  table.model.endUpdateItem(model.item)
                                                              }
                                                          }
                                                      }
                                                      DelegateChoice {
                                                          delegate: Text {
                                                              verticalAlignment: Text.AlignVCenter
                                                              text: model.item[model.name]
                                                          }
                                                      }
                                                  }
                                              }
                                          

                                          If I refresh my TableView with beginResetModel/endResetModel MouseArea starts to work correctly.

                                          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