No "ensure visible" for a QTabBar's current tab. And no other way to adjust the QTabBar's scroll position.



  • When we programmatically select a particular tab in a QTabBar -- using QTabBar::setCurrentIndex (int) -- the scroll position of the QTabBar isn't affected. So when there are more tabs than can fit within the width of the QTabBar, the newly selected (current) tab may not be visible.

    Does anyone know of a way to force a QTabBar's current tab to be scrolled into view within the QTabBar?

    We're using Qt 5.5.1, but I've looked also through the Qt 5.8 API, and don't see any provisions for programmatically affecting the QTabBar's scroll position, nor any "ensure visible" operation or setting for tabs.

    QTabBar is derived directly from QWidget. It's not a QAbstractScrollArea, so no solution is available at that level.



  • in Qt5.8 QTabBar::setCurrentIndex(int index) calls d->makeVisible(index); (makeVisibleis a private method) to ensure it's visible. strange it does not work. what platform are you on?



  • VRonin, thanks for looking at that. I'm seeing that -- call to d->makeVisible(index); -- also in Qt 5.5.1. As is apparent from the code, that "ensure visible" DOES work as long as SOME OTHER tab is currently current -- i.e. in the call to QTabBar::setCurrentIndex(int). Conversely, it doesn't work if the new current index is already current.

    I regard this as a Qt bug. I've run into this a few times -- arguably overzealous optimizations in Qt code. Side effects like this cannot always be skipped. Here is the current Qt 5.5.1 code:

    void QTabBar::setCurrentIndex(int index)
    {
        Q_D(QTabBar);
        if (d->dragInProgress && d->pressedIndex != -1)
            return;
    
        int oldIndex = d->currentIndex;
        if (d->validIndex(index) && d->currentIndex != index) {
            d->currentIndex = index;
            update();
            d->makeVisible(index);
            d->tabList[index].lastTab = oldIndex;
            if (oldIndex >= 0 && oldIndex < count())
                d->layoutTab(oldIndex);
            d->layoutTab(index);
    #ifndef QT_NO_ACCESSIBILITY
    ... ... ...
    #endif
            emit currentChanged(index);
        }
    }
    

    A workaround I've tested is as follows. If the QTabBar's current tab IS the one you want current (but may have been scrolled out of view by the user), you need to first call QTabBar::setCurrentIndex(int) with some other tab, and then call it again with the desired tab.

    I did this (not generalized here, specific to my context) ...

       // Note [Phil, RW 7.1, Qt 5.5.1, 5-2017]: Because of a bug in QTabBar::
       // setCurrentIndex(int), the QTabBar isn't scrolled to the specified
       // index IF that index is already the QTabBar's current index.
       // SEE forum post: https://forum.qt.io/topic/79200/
    
       if ((_objTabBar->currentIndex() == objTabInx) && (_objTabBar->count() > 1))
       {
          _objTabBar->setCurrentIndex ((objTabInx > 0) ? objTabInx-1 : 1);
       }
    
       _objTabBar->setCurrentIndex (objTabInx);
       installSimObj (refObj);
    


Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.