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);
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
.