QListWidget сдвигается, когда пользователь выбирает элемент

У меня есть особая проблема. У меня QListWidget 1000 QListWidgetItem.
У меня есть текстовое поле поиска, которое вызывает следующий код всякий раз, когда кто-то начинает набирать его.

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

В конечном итоге, после того, как мой поиск будет выполнен, у меня будет QListWidget с 600 скрытыми элементами и 400 показанными. Всякий раз, когда я нажимаю на элемент, весь список просто прыгает вниз на несколько строк, так что мой выбор даже не виден на экране.

Я подтвердил, что это setHidden, который, кажется, вызывает его. Если я просто выделю найденные строки, не скрывая / не отображая элементы, выбор не приведет к прокрутке списка вниз.

Поэтому мне интересно, что мне не хватает? Какую функцию мне вызвать, чтобы убедиться, что мой QListWidget не сдвигается при выборе элемента?

Рабочий пример ниже:

#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;

}

Я в основном повторил и изолировал проблему, чтобы быть горизонтальными полосами прокрутки. В моем исходном приложении AND в этом mcve, если вы выберете элемент (например, с индексом 314), список будет прыгать вниз. Однако, если я изменю размер списка не иметь горизонтальные полосы прокрутки, то он не сдвигается.

Итак, теперь, когда я знаю, что проблема в том, чтобы иметь горизонтальную полосу прокрутки, я все еще не уверен, что делать, чтобы предотвратить прыжок.

ОБНОВИТЬ:

Я попытался использовать SIGNAL-SLOT как таковой:

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

Я также попытался создать свой собственный слот, где я явно указываю, что элемент должен быть видимым:

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

Тем не менее, он все еще прыгает вниз и вне поля зрения! Это работает, если я установил ScrollHint в PositionAtCenter! НО, с точки зрения пользовательского опыта, нежелательно, чтобы список смещался каждый раз, когда они щелкают по элементу (даже если этот элемент теперь находится в центре экрана). У меня есть другие варианты?

3

Решение

С помощью QListWidget::scrollToItem Вы можете повторно прокрутить список, чтобы выбранный элемент был виден.

scrollToItem также занимает ScrollHint который позволяет указать, где QListWidget прокручивается до (по умолчанию EnsureVisible)

  • EnsureVisible: прокрутите, чтобы убедиться, что элемент виден.
  • PositionAtTop: прокрутите, чтобы расположить элемент в верхней части области просмотра.
  • PositionAtBottom: прокрутите, чтобы расположить элемент в нижней части области просмотра.
  • PositionAtCenter: прокрутите, чтобы поместить элемент в центр области просмотра.

Полный рабочий пример ниже:

#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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]