Search code examples
c++qtqlistwidgetqlistwidgetitem

QListWidget horizontal scrollbar causes selection to go out of view


I've asked this question previously and a wonderful person lead me to a decent workaround for the issue. However, I am hoping to see if there is a better solution. One that actually prevents any shifting in my QListWidget entirely.

Working demo example

ListDemo zipfile http://nexrem.com/test/ListDemo.zip

ListDemo cpp code

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    myListWidget = new QListWidget();

    /*
     * The signal-slot below is a temporary workaround for the shifting issue.
     * This will ensure that the item selected remains in view,
     * This is achieved by forcing the item to be in the center of the window;
     * however, this has an undesired side-effect of visible 'jumping' as the list
     * scrolls to center the item.
     */
    //connect (myListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this,
    //         SLOT(scrollToItem(QListWidgetItem*)));

    for (int i = 0; i <= 1000; ++i)
    {
        QListWidgetItem * myItem = new QListWidgetItem(myListWidget);
        QString text("");
        for (int i = 0; i <= 40; ++i)
        {
            text.append("W");
        }
        myItem->setText(text + QString::number(i));
    }

    for (int i = 0; i <= 1000; ++i)
    {
        if (i%2)
            myListWidget->item(i)->setHidden(true);
    }
    auto selected = myListWidget->selectedItems();
    if (selected.size() == 1)
    {
        myListWidget->scrollToItem(selected.front());
    }
    setCentralWidget(myListWidget);
}


void MainWindow::scrollToItem(QListWidgetItem * item)
{
    std::cout << "Scrolling to the item." << std::endl;
    myListWidget->scrollToItem(item, QAbstractItemView::PositionAtCenter);
}

The problem: Whenever I have a QListWidget with horizontal scrollbars and hidden rows present, I get an undesired behaviour that whenever a user clicks on an item, it disappears from view, and the entire list shifts down. In the example above, I've hidden every other row, to demonstrate this behaviour.

The workaround: Workaround is having a signal-slot connection that forces the selected item to be scrolled back into view and positioned at the center. Note, that I have to use PositionAtCenter as EnsureVisible does not work. It thinks the item is visible when it is out of view. This workaround is acceptable; however, there is visible 'jump' when your selection is forced to be positioned at the center. This is an undesirable side effect.

At this point I am not sure whether this is a QT bug (I don't think having horizontal scrollbar should force your selection out of view) or my code is missing something vital.

The Fix: As per @G.M.'s comment, all that was missing is myListWidget->setAutoScroll(false);


Solution

  • As mentioned in the comment...

    To prevent automatic scrolling on selection disable the autoScroll property. So, in the example code provided do...

    myListWidget->setAutoScroll(false);
    

    Note that this property also has an effect when items are dragged over the list view so if you want your list view to act as a drop site then you will probably want to re-enable this property when you get a QDragEnterEvent.