QListWidget is shifted when the user selects an item

I have a particular problem. I have a QListWidget of 1000 QListWidgetItem. I have a search text box that triggers the following code when someone starts typing it.

QRegExp regExSearch(searchText, Qt::CaseInsensitive, QRegExp::RegExp);
for (QListWidgetItem * currIt : allItems)
{
    currIt->setHidden( !(currIt->text().contains(regExSearch)) );
}

      

In the end, when my search is done, I will have a QListWidget with 600 hidden items and 400 shown. Whenever I click on an item, the entire list just jumps a few lines so that my selection doesn't even appear on the screen.

I have confirmed that it is setHidden that seems to be calling it. If I just highlight the found rows without hiding / showing the items, the selection does not scroll the list.

As such, I am wondering what am I missing? What function do I call to keep my QListWidget from changing every time I select an item?

Below is a working example:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QListWidget>

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

    QListWidget * myListWidget = new QListWidget();

    for (int i = 0; i <= 1000; ++i)
    {
        QListWidgetItem * myItem = new QListWidgetItem(myListWidget);
        QString text("");
        for (int i = 0; i <= 100; ++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);
    }

    setCentralWidget(myListWidget);
}

MainWindow::~MainWindow()
{
    delete ui;

}

      

I basically replicated and isolated the issue as a horizontal scrollbar. In my original app AND in this mcve, if you select an item (for example at index 314) the list will jump down. However, if I resize the list to not , you have horizontal scrollbars, it won't move.

So now that I know that the problem is with the horizontal scrollbar, I still don't know how to avoid avoiding the transition.

UPDATE:

I tried using SIGNAL-SLOT as such:

connect(myListWidget, SIGNAL(itemClicked(QListWidgetItem*)), myListWidget, 
            SLOT(scrollToItem(const QListWidgetItem*,QAbstractItemView::ScrollHint)));

      

I also tried to create my own slot, where I explicitly state that the element should be visible:

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

      

However, he still jumps down and out of sight! It works if I set ScrollHint to PositionAtCenter

! BUT, from the user's point of view, it is not always desirable to shift the list every time they click on an item (even if that item is now in the center of the screen). Do I have any other options?

+3


source to share


1 answer


Using QListWidget::scrollToItem

, you can scroll through the list so that your selected item is visible.

scrollToItem

also accepts ScrollHint

which lets you specify where to scroll QListWidget

(default EnsureVisible

)

  • EnsureVisible

    : scroll to make sure the item is visible.
  • PositionAtTop

    : Highlight the position at the top of the viewport.
  • PositionAtBottom

    : Highlight a position at the bottom of the viewport.
  • PositionAtCenter

    : Scroll to place the item in the center of the viewport.


Full working example below:

#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include <QLineEdit>
#include <QRegExp>

int main(int argc, char** argv)
{
    QApplication* app = new QApplication(argc, argv);
    QMainWindow*  window = new QMainWindow();

    QWidget widget;
    QVBoxLayout layout(&widget);

    QLineEdit edit;
    layout.addWidget(&edit);

    QListWidget list;
    layout.addWidget(&list);

    for (int i = 0; i < 1000; ++i)
    {
        QListWidgetItem* item = new QListWidgetItem(QString::number(i));
        list.addItem(item);
    }

    QObject::connect(&edit, &QLineEdit::textChanged, [&](const QString& text)
        {
            QRegExp re(text, Qt::CaseInsensitive, QRegExp::RegExp);
            for(int i = 0; i < list.count(); ++i)
            {
                QListWidgetItem* item = list.item(i);
                item->setHidden(!(item->text().contains(re)));
            }

            auto selected = list.selectedItems();
            if (selected.size() == 1)
            {
                list.scrollToItem(selected.front());
            }
        });

    window->setCentralWidget(&widget);
    window->show();
    return app->exec();
}

      

+1


source







All Articles