У меня есть особая проблема. У меня 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
! НО, с точки зрения пользовательского опыта, нежелательно, чтобы список смещался каждый раз, когда они щелкают по элементу (даже если этот элемент теперь находится в центре экрана). У меня есть другие варианты?
С помощью 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();
}
Других решений пока нет …