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 - The very painful way of events propagation
QtWS25 Last Chance

MouseArea - The very painful way of events propagation

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
mouse eventsmouseareaeventblocking
7 Posts 5 Posters 4.4k 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
    jeanmilost
    wrote on 21 Aug 2020, 15:28 last edited by
    #1

    In several of my projects I need to override the default way the mouse interacts with my components, e.g when I need to support new functionalities. For such situations Qt planned the MouseArea component.

    This works well for a huge number of cases, however there are situations where new functionalities are required WITHOUT breaking the already existing mouse behavior provided by the component itself. This is especially true when custom views are written, where advanced behavior are required, like e.g the edition or opening a popup, when an item is clicked on a particular area in the tree, while the tree should continue apply the default behavior, when the user clicked anywhere else, where it's not supposed to react to a particular action, e.g scroll the view when the tree is clicked and the mouse moved.

    However putting a MouseArea somewhere breaks the event propagation to the children components. Qt also planned a such situation, and added properties to handle that, which are propagateComposedEvents and preventStealing. These properties are supposed to resolve the above mentioned issue by changing the way an event is propagated through components.

    And this works... sometimes. It's true that these properties help to resolve many complicated scenarios which may occur, but there are still issues, unfortunately. For example:

    • Overriding the onPressed event stops the propagation inside a particular MouseArea instance. This may be resolved by declaring propagateComposedEvents = true and writing mouse.accepted = false; in the overridden onPressed event, but doing that, many other events are no longer called later, among others onClicked, onDoubleClicked, and any keyboard event.
    • In a more general manner, overriding events in a particular MouseArea may block these events, and if you try to unblock them using the properties planned by Qt in such situations, this may works, but other events are blocked later, which is a side effect from my point of view.

    Finally this is a very complicated rules set, and the ins and outs are not easy to grasp. Unless I miss something. So there is my question: What is the correct configuration to override ALL the mouse events without blocking ANY event in the children components, nor causing ANY side effect, like overriding this event blocks the emission of this other later?

    1 Reply Last reply
    0
    • J Offline
      J Offline
      jeanmilost
      wrote on 21 Aug 2020, 20:26 last edited by
      #2

      Here is another example:

      MouseArea
      {
              id: maFileListView
              anchors.fill: parent
              hoverEnabled: true
              acceptedButtons: Qt.LeftButton | Qt.RightButton
              propagateComposedEvents: true
              preventStealing: true
      
              // called when mouse wheel changes
              onWheel:
              {
                  ...
              }
      }
      

      I added this code in a ListView. Here onWheel is no longer propagated to children, i.e nor the ListView nor its items no longer receive the onWheel event, meaning the scrolling is broken on wheel, despite of the activated properties to propagate and don't steal events, and setting mouse.accepted = false; in the onWheel function cannot be done, as mouse isn't provided by the onWheel event.

      How to resolve a such conflict?

      1 Reply Last reply
      0
      • G Offline
        G Offline
        GrecKo
        Qt Champions 2018
        wrote on 21 Aug 2020, 21:01 last edited by
        #3

        Why are you adding MouseArea on top of clickable or scrollable items?

        mouse.accepted = false; in the onWheel function cannot be done, as mouse isn't provided by the onWheel event.

        the wheel signal provides a wheel object though, you can do wheel.accepted = false.
        The more correct way to get parameter from signal handlers now is to define them as function, not rely on context properties. This has the advantage of letting you name the parameters and being less magic:

        onWheel: function (event) { ... } or onWheel: event => { ... }

        I am curious about your usecase of capturing onWheel on a ListView, can you give more details?

        Anyway, have you looked at Qt Quick Input Handlers? They offer more possibilities and are more lightweight than MouseArea

        J B 2 Replies Last reply 24 Aug 2020, 13:27
        1
        • G GrecKo
          21 Aug 2020, 21:01

          Why are you adding MouseArea on top of clickable or scrollable items?

          mouse.accepted = false; in the onWheel function cannot be done, as mouse isn't provided by the onWheel event.

          the wheel signal provides a wheel object though, you can do wheel.accepted = false.
          The more correct way to get parameter from signal handlers now is to define them as function, not rely on context properties. This has the advantage of letting you name the parameters and being less magic:

          onWheel: function (event) { ... } or onWheel: event => { ... }

          I am curious about your usecase of capturing onWheel on a ListView, can you give more details?

          Anyway, have you looked at Qt Quick Input Handlers? They offer more possibilities and are more lightweight than MouseArea

          J Offline
          J Offline
          jeanmilost
          wrote on 24 Aug 2020, 13:27 last edited by
          #4

          @GrecKo Thank you for your answer.

          the wheel signal provides a wheel object though, you can do wheel.accepted = false.

          Good point, I missed that. This resolve the issue I faced with onWheel.

          The more correct way to get parameter from signal handlers now is to define them as function, not rely on context properties.

          Ok, thanks for the tip. I'll try this way in the future.

          I am curious about your usecase of capturing onWheel on a ListView, can you give more details?

          In my case it's just to close a hint opened from a button on an item in my view. The hint position is linked to the opening button position, and as I use a ToolTip, the hint continue to scroll outside my view when the item containing the button go out of the view. For that reason I want to close this hint before scrolling the view.

          Anyway, have you looked at Qt Quick Input Handlers?

          This seems to be an interesting alternative indeed. However I tried to use it, but it seems not react at all in my view. Here is the code I tested, am I doing something wrong?

          TapHandler
          {
              target: myView
              acceptedButtons: Qt.LeftButton | Qt.RightButton
          
              onTapped:
              {
                  console.log("onTapped called...");
              }
          
              onSingleTapped:
              {
                  console.log("onSingleTapped called...");
              }
          }
          
          1 Reply Last reply
          0
          • R Offline
            R Offline
            Rufledore
            wrote on 19 Oct 2022, 10:37 last edited by
            #5

            I reached the same problem with the QML Map. Have you managed to solve it somehow?

            1 Reply Last reply
            0
            • A Offline
              A Offline
              Asperamanca
              wrote on 19 Oct 2022, 11:34 last edited by
              #6

              I had the same issue, and used a very different approach.

              I installed an event filter on the QQuickView or QQuickWidget. Now I can see all events before they are propagated to QML. As long as I don't filter the event, behavior on the QML side is unchanged (even if I choose to respond to it).

              The big advantage is that I can code certain behaviors in one place for any number of QML components.

              1 Reply Last reply
              0
              • G GrecKo
                21 Aug 2020, 21:01

                Why are you adding MouseArea on top of clickable or scrollable items?

                mouse.accepted = false; in the onWheel function cannot be done, as mouse isn't provided by the onWheel event.

                the wheel signal provides a wheel object though, you can do wheel.accepted = false.
                The more correct way to get parameter from signal handlers now is to define them as function, not rely on context properties. This has the advantage of letting you name the parameters and being less magic:

                onWheel: function (event) { ... } or onWheel: event => { ... }

                I am curious about your usecase of capturing onWheel on a ListView, can you give more details?

                Anyway, have you looked at Qt Quick Input Handlers? They offer more possibilities and are more lightweight than MouseArea

                B Offline
                B Offline
                Bob64
                wrote on 20 Oct 2022, 09:27 last edited by
                #7

                @GrecKo said in MouseArea - The very painful way of events propagation:

                Why are you adding MouseArea on top of clickable or scrollable items?

                Sorry to reply to an old post but this thread got resurrected and this caught my eye. In my case I have a MouseArea on TreeView, which is clickable and scrollable. As I recall (bearing in mind it was some time ago now) it seemed to be the only way to implement a context menu popup when right clicking tree branches. Is there something different I could have done?

                (This is the old TreeView BTW - I haven't looked closely at the new one in Qt 6 to see if that is any different.)

                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