Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
qtws26_logo

The Qt Event of the Year: Qt World Summit 2026

Save Your Spot >
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QScollArea doesn't autoscroll when dragging inside it
Qt 6.12 LTS is out! See what's new in the release blog

QScollArea doesn't autoscroll when dragging inside it

Scheduled Pinned Locked Moved General and Desktop
6 Posts 2 Posters 7.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.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #1

    I have some widgets inside a QScrollArea and I'm dragging between these widgets, the problem is that the QScrollArea doesn't scroll when I'm dragging inside it, so if I want to drag between a widget A to the widget B and the widget B is not visible on the viewport, the QScrollArea doesn't automatically scroll when the mouse moves to the edge of the viewport. Is there any way to implement such auto scroll into the QScrollArea ? I tried to subclass QScrollArea but it isn't receiving the drag events from the widgets inside it.

    1 Reply Last reply
    0
    • raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      you don't necessarily need to subclass the scrollarea, but use an event filter on the QScrollArea's viewport:
      @
      enum { UndefinedDirection, UpDirection, DownDirection, LeftDirection, RightDirection } mDragScrollDirection;

      ...

      mDragScrollTimer.setSingleShot(false); //QTimer
      mDragScrollTimer.setInterval(0);
      connect(&mDragScrollTimer, SIGNAL(timeout()), this, SLOT(doDragScroll()));

      ...

      bool MyClass::eventFilter(QObject* watched, QEvent* event)
      {
      if( mScrollArea->viewport() )
      {
      switch( event->type() )
      {
      case QEvent::DragMove:
      {
      QDragMoveEvent* de = static_cast<QDragMoveEvent*>(event);

                  //determine the position in the viewport and set mDragScrollDirection accordingly
                  //if pos is near the edges start the mDragScrollTimer
              }
              break;
              case QEvent::Drop:
              case QEvent::DragLeave:
              {
                  mDragScrollTimer.stop();
                  mDragScrollDirection = Undefined;
              }
              break;
          }
      }
       return false;
      

      }

      void MyClass::doDragScroll()
      {
      QScrollBar* vsb = mScrollArea->verticalScrollBar();
      QScrollBar* hsb = mScrollArea->horizontalScrollBar();

      switch( mDragScrollDirection )
      {
          case UpDirection:
              if( vsb->isVisible() ) vsb->setValue( vsb->value() - 5 );
          break;
          case DownDirection:
              if( vsb->isVisible() ) vsb->setValue( vsb->value() + 5 );
          break;
          case LeftDirection:
              if( hsb->isVisible() ) hsb->setValue( hsb->value() - 5 );
          break;
          case RightDirection:
              if( hsb->isVisible() ) hsb->setValue( hsb->value() + 5 );
          break;
          case UndefinedDirection:
          default:
          break;
      }
      

      }
      @
      This should give you an idea how to achieve this... ;)

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      0
      • ? Offline
        ? Offline
        A Former User
        wrote on last edited by
        #3

        I tried to use an event filter on the viewport but it isn't receiving the drag'n drop events from the widgets inside the QScrollArea.

        1 Reply Last reply
        0
        • raven-worxR Offline
          raven-worxR Offline
          raven-worx
          Moderators
          wrote on last edited by
          #4

          i see...seems i shot too quickly into the dark.
          There a multiple problems preventing this:

          you need to accept the dragenter event in the viewport to receive consecutive dragmove events

          viewport is the parent for the content of the scrollarea, thus it's not guaranteed to receive all dragmove events at a specific point by event propagation

          you could do the following (ugly) solution:
          @
          MyClass::MyClass()
          {
          qApp->installEventFilter(this);
          this->viewport()->setAcceptDrops(true);
          }

          MyClass::~MyClass()
          {
          qApp->removeEventFilter(this);
          }

          bool MyClass::eventFilter(QObject* watched, QEvent* event)
          {
          if( watched->isWidgetType() )
          {
          QWidget* w = static_cast<QWidget*>(watched);

                if( ! this->isAncestorOf(w) )
                     return false;
                
              switch( event->type() )
              {
                  case QEvent::DragMove:
                  {
                      QDragMoveEvent* de = static_cast<QDragMoveEvent*>(event);
                     
                      //determine the position in the viewport and set mDragScrollDirection accordingly
                      
                      if( calculatedDirection == mDragScrollDirection )
                            return false;
          
                      mDragScrollDirection = calculatedDirection;
          
                      if( mDragScrollDirection == UndefinedDirection && mDragScrollTimer.isActive() )
                              mDragScrollTimer.stop();
                      else if( ! mDragScrollTimer.isActive() )
                              mDragScrollTimer.start();
                  }
                  break;
                  case QEvent::Drop:
                  case QEvent::DragLeave:
                  {
                      mDragScrollTimer.stop();
                      mDragScrollDirection = Undefined;
                  }
                  break;
              }
          }
          
           return false;
          

          }
          @

          you may have to listen (eventFilter) the viewports dragEnter event and simply accept() it, to ensure you will receive dragMove events.

          --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
          If you have a question please use the forum so others can benefit from the solution in the future

          1 Reply Last reply
          0
          • ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #5

            Thanks for the reply, the problem you pointed on the item 2 is very problematic on my case because a have a lots of widgets inside the viewport, and since they are handling the drag events, these events aren't propagated to the viewport event filter, so if I'm dragging from a widget to the viewport there is no problem because it receives the event, but when I'm dragging from the widget to outside of the QScrollArea the event isn't received, I'm starting to wonder that the only way to solve this is to use the notify() event from the QApplication, which captures all events from the application. I'm very surprised that this simple UI behavior used by lots of UIs is so hard to implement in Qt.

            1 Reply Last reply
            0
            • raven-worxR Offline
              raven-worxR Offline
              raven-worx
              Moderators
              wrote on last edited by
              #6

              [quote author="tarantulae" date="1368197356"]Thanks for the reply, the problem you pointed on the item 2 is very problematic on my case because a have a lots of widgets inside the viewport, and since they are handling the drag events, these events aren't propagated to the viewport event filter[/quote]
              thats why i installed the eventFilter on the QApplication instance (see the code).

              [quote author="tarantulae" date="1368197356"]so if I'm dragging from a widget to the viewport there is no problem because it receives the event, but when I'm dragging from the widget to outside of the QScrollArea the event isn't received[/quote]
              why do you wanna receive an event outside the qscrollarea (and it's viewport) at all?! Its the only purpose to auto scroll right?!

              --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
              If you have a question please use the forum so others can benefit from the solution in the future

              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
              • Unsolved