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. [Solved] Is it possible to have two mouse areas process the same mouse event?
Qt 6.11 is out! See what's new in the release blog

[Solved] Is it possible to have two mouse areas process the same mouse event?

Scheduled Pinned Locked Moved QML and Qt Quick
11 Posts 7 Posters 11.2k Views 1 Watching
  • 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.
  • B Offline
    B Offline
    bundickt
    wrote on last edited by
    #1

    I want to have a popup overlay in my qml application. If you click outside of the popup overlay it needs to close the popup and send the mouse event to mouse area that would of received the event if the popup overlay was not visible.

    Example code:
    @
    import QtQuick 1.0

    Rectangle {
    width: 500;
    height: 500;

    Rectangle {
    id: r1;
    anchors.fill: parent;
    color: "slategray";

    MouseArea {
    id: m1;

    anchors.fill: parent;

    onClicked: {
    console.log("m1 clicked " + mouse.x + ", " + mouse.y);
    }
    }
    }

    Item {
    id: popupOverlay;

    anchors.fill: parent;

    MouseArea {
    id: m3;

    anchors.fill: parent;

    onClicked: {
    console.log("m3 clicked " + mouse.x + ", " + mouse.y);

    // close popupOverlay and have m1 process the mouse event
    popupOverlay.visible = false;
    

    }
    }

    Rectangle {
    id: r2;
    anchors.fill: parent;
    anchors.margins: 50;

    color: "black";
    opacity: 0.5;

    MouseArea {
    id: m2;
    anchors.fill: parent;

    onClicked: {
     console.log("Don't close overlay");
    }
    

    }
    }
    }
    }

    @

    In that example I am only able to close the popup when m3 is clicked.

    1 Reply Last reply
    0
    • D Offline
      D Offline
      Diph
      wrote on last edited by
      #2

      What if you define a function which process the events and call it from m3 and m1 clicked events?

      1 Reply Last reply
      0
      • B Offline
        B Offline
        bundickt
        wrote on last edited by
        #3

        This is just a small example, I have hundreds of mouse areas and about 10 popups. I would need to traverse the graphics stack to see what mouse areas are actually being drawn and then find which ones overlap the x, and y locations of the mouse event. Then I could call that functions. I was hoping I wouldn't have to do something like that.

        I have implemented this with GTK by disabling the "mouse area" and re-sending the mouse event and then re-enabling the "mouse area". I was hoping qt quick already supported something like that.

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mlong
          wrote on last edited by
          #4

          Is it sufficient to make sure that the "accepted":http://doc.qt.nokia.com/4.7-snapshot/qml-mouseevent.html#accepted-prop property on the MouseEvent in the MouseArea handler is set to false so that the event propagates to other MouseAreas?

          Software Engineer
          My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

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

            The accepted property of the MouseEvent parameter is ignored in this handler.

            http://doc.qt.nokia.com/latest/qml-mousearea.html#onClicked-signal

            Maybe only solution is to remove m3 mouse area and check in m1 onClicked if click was inside the overlay area and the overlay area was visible.

            1 Reply Last reply
            0
            • M Offline
              M Offline
              minimoog77
              wrote on last edited by
              #6

              Related bug report https://bugreports.qt.nokia.com/browse/QTBUG-13007

              1 Reply Last reply
              0
              • A Offline
                A Offline
                Amnell
                wrote on last edited by
                #7

                [quote author="Diph" date="1314126601"] The accepted property of the MouseEvent parameter is ignored in this handler.

                http://doc.qt.nokia.com/latest/qml-mousearea.html#onClicked-signal

                Maybe only solution is to remove m3 mouse area and check in m1 onClicked if click was inside the overlay area and the overlay area was visible.[/quote]

                onClicked is called after a onPressed and a onReleased, so if onPressed/onReleased doesn't accept the event, onClicked won't be called.

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  shullw
                  wrote on last edited by
                  #8

                  The visibility is a great way to pull this off. I have set multiple MouseAreas as the same area before in a project and just made them visible true or false when I needed them. The other thing you might think about doing is setting the z: . If you change the the one you want to be the top most to z: 3 than it should put it on top. Just an idea.

                  A QML Purest Point of View!

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    bundickt
                    wrote on last edited by
                    #9

                    My Solution:

                    Created an EventFilter plugin, that installs an event filter on that instance of the qml element.

                    Plugin:
                    Added signals for mouse pressed (x, y) and mouse released (x, y).
                    Added a property to enable/disable the filter.

                    QML:
                    In my QML I put an EventFilter element in all of my popup overlays.
                    When the overlay is visible I enable its associated EventFilter.
                    When the EventFilter gets the mouse pressed signal I see if the x and y are outside the overlay.
                    If the mouse press is outside the overlay I make the overlay not visible.

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      allopen
                      wrote on last edited by
                      #10

                      would you like to share your code?
                      are there any better ways in Qt5?

                      [quote author="bundickt" date="1314207209"]My Solution:

                      Created an EventFilter plugin, that installs an event filter on that instance of the qml element.

                      Plugin:
                      Added signals for mouse pressed (x, y) and mouse released (x, y).
                      Added a property to enable/disable the filter.

                      QML:
                      In my QML I put an EventFilter element in all of my popup overlays.
                      When the overlay is visible I enable its associated EventFilter.
                      When the EventFilter gets the mouse pressed signal I see if the x and y are outside the overlay.
                      If the mouse press is outside the overlay I make the overlay not visible.[/quote]

                      1 Reply Last reply
                      0
                      • B Offline
                        B Offline
                        bundickt
                        wrote on last edited by
                        #11

                        I haven't started using Qt 5, so I'm not sure if it does this.

                        This plugin is good for this and it's also good for implementing a screen saving feature.

                        Here is the plugin code:

                        @
                        #include <qdeclarative.h>
                        #include <QObject>
                        #include <QEvent>
                        #include <QKeyEvent>
                        #include <QMouseEvent>
                        #include <QBool>
                        #include <QApplication>
                        #include <QDebug>

                        class QMLKeyEvent : public QObject {
                        Q_OBJECT
                        Q_PROPERTY(int key READ key)
                        Q_PROPERTY(QString text READ text)
                        Q_PROPERTY(int modifiers READ modifiers)
                        Q_PROPERTY(bool isAutoRepeat READ isAutoRepeat)
                        Q_PROPERTY(int count READ count)
                        Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
                        Q_PROPERTY(int nativeScanCode READ nativeScanCode)
                        Q_PROPERTY(int type READ type)

                        public:
                        QMLKeyEvent(const QKeyEvent &ke, const int n = 0) : _event(ke), _nativeScanCode(n) { _event.setAccepted((false)); }

                        int key() const { return _event.key(); }
                        QString text() const { return _event.text(); }
                        int modifiers() const { return _event.modifiers(); }
                        bool isAutoRepeat() const { return _event.isAutoRepeat(); }
                        int count() const { return _event.count(); }
                        bool isAccepted() const { return _event.isAccepted(); }
                        void setAccepted(bool accepted) { _event.setAccepted(accepted); }
                        int nativeScanCode() const { return _nativeScanCode; }
                        int type() const { return _event.type(); }

                        private:
                        QKeyEvent _event;
                        int _nativeScanCode;
                        };

                        class QMLMouseEvent : public QObject {
                        Q_OBJECT
                        Q_PROPERTY(int x READ x)
                        Q_PROPERTY(int y READ y)
                        Q_PROPERTY(int globalX READ globalX)
                        Q_PROPERTY(int globalY READ globalY)
                        Q_PROPERTY(int button READ button)
                        Q_PROPERTY(int buttons READ buttons)
                        Q_PROPERTY(int modifiers READ modifiers)
                        Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)

                        public:
                        QMLMouseEvent(const QMouseEvent &me) : _event(me) { _event.setAccepted(false); }

                        int x() const { return _event.x(); }
                        int y() const { return _event.y(); }
                        int globalX() const { return _event.globalX(); }
                        int globalY() const { return _event.globalY(); }
                        int button() const { return _event.button(); }
                        int buttons() const { return _event.buttons(); }
                        int modifiers() const { return _event.modifiers(); }

                        bool isAccepted() { return _event.isAccepted(); }
                        void setAccepted(bool accepted) { _event.setAccepted(accepted); }

                        private:
                        QMouseEvent _event;
                        };

                        QML_DECLARE_TYPE(QMLKeyEvent)
                        QML_DECLARE_TYPE(QMLMouseEvent)

                        class UserEventFilter : public QObject
                        {
                        Q_OBJECT

                        Q_PROPERTY(bool enabled READ getEnabled WRITE setEnabled NOTIFY enabledChanged)

                        public:
                        UserEventFilter(QObject * parent = 0);
                        virtual ~UserEventFilter();

                        public: // for properties
                        bool getEnabled() const;
                        void setEnabled(const bool enabled);

                        signals: // for properties
                        void enabledChanged(bool newEnabled);

                        signals:
                        void userEventOccurred();

                        void keyPressed(QMLKeyEvent *event);
                        void keyReleased(QMLKeyEvent *event);

                        void mousePressed(QMLMouseEvent *event);
                        void mouseReleased(QMLMouseEvent *event);
                        void mouseMoved(QMLMouseEvent *event);

                        private:
                        bool processKeyPress(QEvent *event);
                        bool processKeyRelease(QEvent *event);
                        bool processMouseButtonPress(QEvent *event);
                        bool processMouseButtonRelease(QEvent *event);
                        bool processMouseMove(QEvent *event);

                        private: // for properties
                        bool _enabled;

                        protected:
                        bool eventFilter(QObject * obj, QEvent * event);
                        };

                        UserEventFilter::UserEventFilter(QObject * parent) : QObject(parent) {
                        _enabled = true;
                        qApp->installEventFilter(this);
                        }

                        UserEventFilter::~UserEventFilter() {
                        }

                        bool UserEventFilter::getEnabled() const {
                        return _enabled;
                        }

                        void UserEventFilter::setEnabled(const bool enabled) {
                        if(_enabled != enabled) {
                        _enabled = enabled;
                        emit enabledChanged(_enabled);
                        }
                        }

                        bool UserEventFilter::processKeyPress(QEvent *event) {
                        QKeyEvent *e = static_cast<QKeyEvent *>(event);
                        QMLKeyEvent ke(*e, e->nativeScanCode());

                        ke.setAccepted(false);

                        emit keyPressed(&ke);
                        emit userEventOccurred();

                        return ke.isAccepted();
                        }

                        bool UserEventFilter::processKeyRelease(QEvent *event) {
                        QKeyEvent *e = static_cast<QKeyEvent *>(event);
                        QMLKeyEvent ke(*e, e->nativeScanCode());
                        ke.setAccepted(false);

                        emit keyReleased(&ke);
                        emit userEventOccurred();

                        return ke.isAccepted();
                        }

                        bool UserEventFilter::processMouseButtonPress(QEvent *event) {
                        QMLMouseEvent me(*static_cast<QMouseEvent *>(event));
                        me.setAccepted(false);

                        emit mousePressed(&me);
                        emit userEventOccurred();

                        return me.isAccepted();
                        }

                        bool UserEventFilter::processMouseButtonRelease(QEvent *event) {
                        QMLMouseEvent me(*static_cast<QMouseEvent *>(event));
                        me.setAccepted(false);

                        emit mouseReleased(&me);
                        emit userEventOccurred();

                        return me.isAccepted();
                        }

                        bool UserEventFilter::processMouseMove(QEvent *event) {
                        QMLMouseEvent me(*static_cast<QMouseEvent *>(event));
                        me.setAccepted(false);

                        emit mouseMoved(&me);
                        emit userEventOccurred();

                        return me.isAccepted();
                        }

                        bool UserEventFilter::eventFilter(QObject * obj, QEvent * event) {
                        Q_UNUSED(obj);

                        if(_enabled) {
                        switch(event->type()) {
                        case QEvent::KeyPress:
                        return processKeyPress(event);
                        break;

                        case QEvent::KeyRelease:
                        return processKeyRelease(event);
                        break;

                        case QEvent::MouseButtonPress:
                        return processMouseButtonPress(event);
                        break;

                        case QEvent::MouseButtonRelease:
                        return processMouseButtonRelease(event);
                        break;

                        case QEvent::MouseMove:
                        return processMouseMove(event);
                        break;

                        default:
                        break;
                        }
                        }

                        return QObject::eventFilter(obj, event);
                        }

                        @

                        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