Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. detect if mouse buttons are pressed when sliding into widget
QtWS25 Last Chance

detect if mouse buttons are pressed when sliding into widget

Scheduled Pinned Locked Moved Solved General and Desktop
17 Posts 5 Posters 4.9k 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.
  • C Offline
    C Offline
    Chris Kawa
    Lifetime Qt Champion
    wrote on 3 Oct 2019, 15:59 last edited by Chris Kawa 10 Mar 2019, 16:22
    #2

    Widgets grabMouse() on mouse press meaning all following mouse events go to that pressed widget until mouse is released. This is to ensure that widgets properly update their state. For example it would be very difficult to handle clicks correctly if press went to one widget and release to another.

    What you can do is installEventFilter() on both widgets and handle their presses, moves and releases there. Since you would get events from both widgets, no matter which grabbed the mouse, you could there check over which widget the event occurred.

    Btw. you don't need to all those bound checks manually. QRect has a handy method contains(), so you can just do rect.contains(point);

    Just be mindful that the event->pos() is in coordinates of the widget that received the event, so if you want to go with the event filter you will need to map the point and rect coordinates to the same coord space, e.g. the global space:

    event->globalPos() will give you the mouse position in global space
    QRect r(widget->mapToGlobal(QPoint(0,0)), widget->size()) will give you the widget rectangle in global space

    1 Reply Last reply
    2
    • S Offline
      S Offline
      sandro4912
      wrote on 3 Oct 2019, 16:15 last edited by
      #3

      How can I distinguish between mouseMoveEvent , mouseReleaseEvent and mousePressEvent in the event filter?

      1 Reply Last reply
      0
      • C Offline
        C Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on 3 Oct 2019, 16:19 last edited by
        #4

        Inside the event handler you can check the event type:

        bool YourClass::eventFilter(QObject *watched, QEvent *event)
        {
           if(event->type() == QEvent::MouseButtonPress)
           {
              QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
              // do something...
           }
        
           return false; // means handle event as usual
        }
        

        ...and so on for other event types. Here are all possible event types.

        1 Reply Last reply
        2
        • S Offline
          S Offline
          sandro4912
          wrote on 3 Oct 2019, 16:39 last edited by
          #5

          @Chris-Kawa said in detect if mouse buttons are pressed when sliding into widget:

          if(event->type() == QEvent::MouseButtonPress)
          {
          QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
          // do something...
          }

          Ok I have one more concern. Before i handled mouseMoveEvent , mouseReleaseEvent and mousePressEvent in the Cell class. To implement them I used private functions and members of the Cell class. To implement the behaviour now i have to make them public or frind with the Event filter class. Doesn't that break encapusulation?

          C 1 Reply Last reply 4 Oct 2019, 01:39
          0
          • S sandro4912
            3 Oct 2019, 16:39

            @Chris-Kawa said in detect if mouse buttons are pressed when sliding into widget:

            if(event->type() == QEvent::MouseButtonPress)
            {
            QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
            // do something...
            }

            Ok I have one more concern. Before i handled mouseMoveEvent , mouseReleaseEvent and mousePressEvent in the Cell class. To implement them I used private functions and members of the Cell class. To implement the behaviour now i have to make them public or frind with the Event filter class. Doesn't that break encapusulation?

            C Offline
            C Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on 4 Oct 2019, 01:39 last edited by
            #6

            @sandro4912 said in detect if mouse buttons are pressed when sliding into widget:

            To implement the behaviour now i have to make them public or frind with the Event filter class.

            Can't you just call a public function on that Cell class that will call all those private things?

            1 Reply Last reply
            1
            • S Offline
              S Offline
              sandro4912
              wrote on 4 Oct 2019, 06:19 last edited by
              #7

              i tryed it out however i still have the same issue:

              
              bool CellInputHandler::eventFilter(QObject *watched, QEvent *event)
              {
                  auto cell = qobject_cast<Cell *>(watched);
              
                  if(event->type() == QEvent::MouseButtonPress){
                     auto mouse_event = static_cast<QMouseEvent*>(event);
                     cell->handleMousePressEvent(mouse_event);
                     return true;
                  }
                  if(event->type() == QEvent::MouseButtonRelease){
                     auto mouse_event = static_cast<QMouseEvent*>(event);
                     cell->handleMouseReleaseEvent(mouse_event);
                     return true;
                  }
                  if(event->type() == QEvent::MouseMove) {
                      auto mouse_event = static_cast<QMouseEvent*>(event);
                      QRect rect{cell->mapToGlobal(QPoint(0, 0)), cell->size()};
              
                      if(rect.contains(mouse_event->globalPos())) {
              
                          if(mouse_event->buttons() & Qt::LeftButton &&
                              mouse_event->buttons() & Qt::RightButton) {
              
                              cell->handleMouseMoveEventInside(mouse_event);
                          }
                      }
                      else {
                          cell->handleMouseMoveEventOutside(mouse_event);
                      }
                      return true;
                  }
                  return false;
              }
              
              
              

              Press and Release seem to work fine like they already did. However the move still only detects one widget.

              In Cell i added this:

              void Cell::handleMouseMoveEventInside(QMouseEvent *event)
              {
                      qDebug() << "Entered";
              }
              
              void Cell::handleMouseMoveEventOutside(QMouseEvent *event)
              {
                      qDebug() << "Left";
              }
              

              Still i only see Entered and Left from the widget i first clicked down the mouse buttons

              1 Reply Last reply
              0
              • S sandro4912
                3 Oct 2019, 15:43

                I want to do the following:

                I have two exactly the same widgets which are next to each other. I want to push down a mouse button in the first one and then slide into the second widget to perform a action there. So the second widget should detect that the mouse button is down and i slided in.

                However it looks like the second widget never gets informed that i slided into it. Strangely I can see the slide in if i go out of the first widget and back in.

                void Cell::mouseMoveEvent(QMouseEvent *event)
                {
                    if(!mouseIsOutside(event)  &&
                            event->buttons() & Qt::LeftButton ) {
                
                        qDebug() << "Entered";
                
                    }
                }
                
                bool Cell::mouseIsOutside(QMouseEvent *event)
                {
                    auto pos = event->pos();
                    auto rect = this->rect();
                
                    if(pos.x() < rect.x()) {
                        return true;
                    }
                    if(pos.x() > rect.x() + rect.width()) {
                        return true;
                    }
                    if(pos.y() < rect.y()) {
                        return true;
                    }
                    if(pos.y() > rect.y() + rect.height()) {
                        return true;
                    }
                    return false;
                }
                
                A Offline
                A Offline
                Asperamanca
                wrote on 4 Oct 2019, 11:15 last edited by
                #8

                @sandro4912 It sounds a bit like a drag-and-drop operation to me. Wouldn't that work for you?

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  sandro4912
                  wrote on 4 Oct 2019, 16:38 last edited by
                  #9

                  You mean using drag and drop in the event filter to transfer that mouse buttons are pressed both?

                  M 1 Reply Last reply 4 Oct 2019, 18:00
                  0
                  • S sandro4912
                    4 Oct 2019, 16:38

                    You mean using drag and drop in the event filter to transfer that mouse buttons are pressed both?

                    M Offline
                    M Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on 4 Oct 2019, 18:00 last edited by
                    #10

                    @sandro4912
                    Hi
                    Do you have
                    setMouseTracking(true);
                    on widget 2 ?

                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      sandro4912
                      wrote on 4 Oct 2019, 18:24 last edited by sandro4912 10 Apr 2019, 18:24
                      #11

                      @mrjj said in detect if mouse buttons are pressed when sliding into widget:

                      Hi

                      Yes it is enabled on both widgets(they are the same widgets)

                      M 1 Reply Last reply 4 Oct 2019, 18:37
                      0
                      • S sandro4912
                        4 Oct 2019, 18:24

                        @mrjj said in detect if mouse buttons are pressed when sliding into widget:

                        Hi

                        Yes it is enabled on both widgets(they are the same widgets)

                        M Offline
                        M Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on 4 Oct 2019, 18:37 last edited by
                        #12

                        @sandro4912
                        Ok. :)
                        was just a shot.

                        1 Reply Last reply
                        0
                        • S Offline
                          S Offline
                          sandro4912
                          wrote on 4 Oct 2019, 19:10 last edited by
                          #13

                          I really wonder how the issue could get solved. Annother Information i maybe forgot to tell.

                          Both widgets are inside annother widget. Could that help?

                          M 1 Reply Last reply 4 Oct 2019, 19:17
                          0
                          • S sandro4912
                            4 Oct 2019, 19:10

                            I really wonder how the issue could get solved. Annother Information i maybe forgot to tell.

                            Both widgets are inside annother widget. Could that help?

                            M Offline
                            M Offline
                            mrjj
                            Lifetime Qt Champion
                            wrote on 4 Oct 2019, 19:17 last edited by
                            #14

                            @sandro4912
                            Hi
                            The issue is that you only see

                            event->type() == QEvent::MouseMove

                            for one of the widgets ?

                            O 1 Reply Last reply 4 Oct 2019, 19:39
                            0
                            • M mrjj
                              4 Oct 2019, 19:17

                              @sandro4912
                              Hi
                              The issue is that you only see

                              event->type() == QEvent::MouseMove

                              for one of the widgets ?

                              O Offline
                              O Offline
                              ofmrew
                              wrote on 4 Oct 2019, 19:39 last edited by
                              #15

                              @mrjj I believe that you need to set a variable, addressable from each cell, that indicates that the mouse button has been pressed. My concern with this is that what happens if the mouse button is released in another widget? Hover events might be helpful.

                              1 Reply Last reply
                              0
                              • C Offline
                                C Offline
                                Chris Kawa
                                Lifetime Qt Champion
                                wrote on 4 Oct 2019, 19:58 last edited by
                                #16

                                The problem is you're checking the rectangle of the wrong widget. As I said the widget grabs mouse when you press, so cell is always gonna be the widget that gets the events, the one you pressed on, not the one you're hovering over.

                                You need to get the rectangle of the other widget from somewhere.

                                Here's a little working example. Maybe you'll find it useful:

                                #include <QApplication>
                                #include <QPushButton>
                                #include <QHBoxLayout>
                                #include <QEvent>
                                #include <QDebug>
                                
                                struct FilterClass : public QObject
                                {
                                    bool eventFilter(QObject*, QEvent* evt)
                                    {
                                        if (evt->type() == QEvent::MouseMove)
                                        {
                                            auto move_evt = static_cast<QMouseEvent*>(evt);
                                            if (move_evt->buttons().testFlag(Qt::LeftButton) &&
                                                move_evt->buttons().testFlag(Qt::RightButton))
                                                qDebug() << "Mouse over" << qApp->widgetAt(move_evt->globalPos());
                                        }
                                
                                        return false;
                                    }
                                };
                                
                                int main(int argc, char *argv[])
                                {
                                    QApplication a(argc, argv);
                                
                                    FilterClass filter;
                                    QWidget w;
                                    w.setLayout(new QHBoxLayout());
                                    w.layout()->addWidget(new QPushButton("Button 1"));
                                    w.layout()->addWidget(new QPushButton("Button 2"));
                                    for (auto c : w.children()) c->installEventFilter(&filter);
                                
                                    w.show();
                                    return a.exec();
                                }
                                
                                1 Reply Last reply
                                2
                                • S Offline
                                  S Offline
                                  sandro4912
                                  wrote on 5 Oct 2019, 15:31 last edited by
                                  #17

                                  I could solve the issue with the example code.

                                  I had to add a member which remembers the last cell in the event filer. Than i could solve my Issue like this:

                                  if(event->type() == QEvent::MouseMove) {
                                      auto mouse_event = static_cast<QMouseEvent*>(event);
                                      QRect rect{cell->mapToGlobal(QPoint(0, 0)), cell->size()};
                                  
                                      if(mouse_event->buttons().testFlag(Qt::LeftButton) &&
                                          mouse_event->buttons().testFlag(Qt::RightButton)) {
                                  
                                          auto widget = qApp->widgetAt(mouse_event->globalPos());
                                  
                                          if(widget) {
                                              auto currentCell = qobject_cast<Cell *>(widget);
                                  
                                              if(!currentCell) {
                                                  if(mLastCell) {
                                                      mLastCell->handleMouseMoveEventOutside(mouse_event);
                                                  }
                                                  mLastCell = nullptr;
                                                  return true;
                                              }
                                  
                                              if(currentCell != mLastCell) {
                                                  if(mLastCell) {
                                                      mLastCell->handleMouseMoveEventOutside(mouse_event);
                                                  }
                                                  currentCell->handleMouseMoveEventInside(mouse_event);
                                                  mLastCell = currentCell;
                                              }
                                          }
                                          return true;
                                      }
                                  }
                                  
                                  1 Reply Last reply
                                  0

                                  11/17

                                  4 Oct 2019, 18:24

                                  • Login

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