当用户选择一个项目时 QListWidget 移动
QListWidget shifts when user selects an item
我有一个特殊问题。我有 1000 个 QListWidgetItem 的 QListWidget。
我有一个搜索文本框,只要有人开始输入它就会触发以下代码。
QRegExp regExSearch(searchText, Qt::CaseInsensitive, QRegExp::RegExp);
for (QListWidgetItem * currIt : allItems)
{
currIt->setHidden( !(currIt->text().contains(regExSearch)) );
}
一旦执行搜索,我将得到一个 QListWidget,其中隐藏了 600 个项目,显示了 400 个项目。每当我单击一个项目时,整个列表只会向下跳几行,因此我的 selection 甚至在屏幕上都看不到。
我已经确认似乎是 setHidden 引起的。如果我只是突出显示找到的行,没有 hiding/showing 项,selection 不会导致列表向下滚动。
因此,我想知道我错过了什么?我调用哪个函数,以确保我的 QListWidget 不会在我 select 一个项目时移动?
下面的工作示例:
#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;
}
我基本上复制并隔离了水平滚动条的问题。在我原来的应用程序和这个 mcve 中,如果您 select 一个项目(例如在索引 314 处),列表将向下跳转。但是,如果我将列表的大小调整为 not 有水平滚动条,那么它不会移动。
现在我知道问题出在水平滚动条上,但我仍然不确定如何防止发生跳转。
更新:
我曾尝试这样使用 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
: scroll to ensure that the item is visible.
PositionAtTop
: scroll to position the item at the top of the viewport.
PositionAtBottom
: scroll to position the item at the bottom of the viewport.
PositionAtCenter
: scroll to position the item at the center of the viewport.
下面是完整的工作示例:
#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();
}
我遇到了同样的问题。
禁用自动滚动解决了问题:
list.setAutoScroll(false);
其中 list 是 QListWidget 类型(如您的示例所示)。
看:
https://doc.qt.io/qt-5/qabstractitemview.html#autoScroll-prop
我有一个特殊问题。我有 1000 个 QListWidgetItem 的 QListWidget。 我有一个搜索文本框,只要有人开始输入它就会触发以下代码。
QRegExp regExSearch(searchText, Qt::CaseInsensitive, QRegExp::RegExp);
for (QListWidgetItem * currIt : allItems)
{
currIt->setHidden( !(currIt->text().contains(regExSearch)) );
}
一旦执行搜索,我将得到一个 QListWidget,其中隐藏了 600 个项目,显示了 400 个项目。每当我单击一个项目时,整个列表只会向下跳几行,因此我的 selection 甚至在屏幕上都看不到。
我已经确认似乎是 setHidden 引起的。如果我只是突出显示找到的行,没有 hiding/showing 项,selection 不会导致列表向下滚动。
因此,我想知道我错过了什么?我调用哪个函数,以确保我的 QListWidget 不会在我 select 一个项目时移动?
下面的工作示例:
#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;
}
我基本上复制并隔离了水平滚动条的问题。在我原来的应用程序和这个 mcve 中,如果您 select 一个项目(例如在索引 314 处),列表将向下跳转。但是,如果我将列表的大小调整为 not 有水平滚动条,那么它不会移动。
现在我知道问题出在水平滚动条上,但我仍然不确定如何防止发生跳转。
更新:
我曾尝试这样使用 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
: scroll to ensure that the item is visible.PositionAtTop
: scroll to position the item at the top of the viewport.PositionAtBottom
: scroll to position the item at the bottom of the viewport.PositionAtCenter
: scroll to position the item at the center of the viewport.
下面是完整的工作示例:
#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();
}
我遇到了同样的问题。 禁用自动滚动解决了问题:
list.setAutoScroll(false);
其中 list 是 QListWidget 类型(如您的示例所示)。 看: https://doc.qt.io/qt-5/qabstractitemview.html#autoScroll-prop