Results 1 to 5 of 5

Thread: QScrollArea: How to avoid automatic scroll actions?

  1. #1
    Join Date
    Aug 2008
    Posts
    8
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default QScrollArea: How to avoid automatic scroll actions?

    Hi!

    I have a QScrollArea showing a QVBoxLayout with multiple widgets. At certain points of time, some (child-)widgets need to be disabled or enabled. Sometimes this is triggered by user actions on other widgets, sometimes this is triggered by internal events like timers, without any direct input from the user.

    My problem is that QScrollArea automatically ensures visibility for widgets, as they become enabled. In my case, this leads to unwanted scroll actions. I.e., the user changes a control in the upper region of the scrolled area, and, as a result, QScrollArea automatically scrolls down. This can be quite annoying for the user, when the currently used control suddenly jumps out of sight.

    The only solution I'm aware of, is disabling the whole scrolled widget first, then enabling the intended child widget, and finally enabling the whole scrolled widget again. This works pretty well, except for simultaneous user actions being aborted. As I said, sometimes this is triggered by something like timers, so the user might use, lets say, a QComboBox inside the scrolled area, while the whole scrolled widget is disabled for a short period of time. This leads to user interactions being randomly aborted without any obvious reason. (Which is also annoying...)

    Any other ideas?

    Thanks!
    Philipp

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea: How to avoid automatic scroll actions?

    I think you should reimplement eventFilter() for the scroll area and make sure the scroll area doesn't react on the widget's focusin event. Currently the filter looks like this:
    Qt Code:
    1. bool QScrollArea::eventFilter(QObject *o, QEvent *e)
    2. {
    3. #ifdef QT_KEYPAD_NAVIGATION
    4. if (d->widget && o != d->widget && e->type() == QEvent::FocusIn
    5. && QApplication::keypadNavigationEnabled()) {
    6. if (o->isWidgetType())
    7. ensureWidgetVisible(static_cast<QWidget *>(o));
    8. }
    9. #endif
    10. if (o == d->widget && e->type() == QEvent::Resize)
    11. d->updateScrollBars();
    12.  
    13. return false;
    14. }
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Aug 2008
    Posts
    8
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: QScrollArea: How to avoid automatic scroll actions?

    Thanks for your advice. Nevertheless, I wasn't able to solve my problem yet.

    I tried to subclass QScrollArea with the standard implementation you posted. (Just to have a starting point for modifications) But I wasnt able to compile because of missing "QScrollAreaPrivate" definitions.

    Then I tried this:
    Qt Code:
    1. bool NonJumpingScrollArea::eventFilter(QObject *o, QEvent *e)
    2. {
    3. if ( e->type() == QEvent::FocusIn )
    4. {
    5. return true;
    6. }
    7. return QScrollArea::eventFilter(o,e);
    8. }
    To copy to clipboard, switch view to plain text mode 
    , but the ScrollArea is still reacting.
    Also, changing the filtered signal type to QEvent::EnabledChange didn't help.

  4. #4
    Join Date
    Aug 2008
    Posts
    8
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: QScrollArea: How to avoid automatic scroll actions? [solved]

    Ok, I finally found the real reason for automatic scroll actions.

    I use a PushButton, which gets temporarily disabled after it has been clicked. By clicking on it, the pushbutton receives the keyboard focus. Then, disabling this button leads to a call to focusNextChild, which ensures that nextChild is visible.

    In short: To avoid self-scrolling inside QScrollarea, never disable focus-owning-widgets. Always call clearFocus first.

  5. The following user says thank you to PhilippB for this useful post:

    liminf (31st October 2012)

  6. #5
    Join Date
    Oct 2012
    Posts
    1
    Thanks
    1
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    Unix/X11

    Default Re: QScrollArea: How to avoid automatic scroll actions? [solved]

    I have also encountered this "gotcha". In my case, I had a list of widgets managed by a vertical layout within the QScrollArea. Each of the child widgets have a QCheckBox to enable group actions. Once the group action took place, I hid those QCheckBox widgets whose check state was "Qt.Checked"; however, this produced an unexpected result as the QScrollView subsequently scrolled to a seemingly random location. I tried several things to try to prevent this autoscroll behavior (reimplement the QScrollArea::scrollContentsBy(), installed an event filter on both the QScrollArea and QScrollArea::widget() resizeEvents, etc.) but the only thing that worked was to stop calling QCheckBox::hide().

    Thanks to PhilippB for identifying the solution. After simply setting the QCheckBox::setFocusPolicy(Qt::NoFocus), I was able to hide the check box without the scrolling behavior.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.