如何有效地选择符合某些条件的 QTableView 行的子集?
Posted
技术标签:
【中文标题】如何有效地选择符合某些条件的 QTableView 行的子集?【英文标题】:How to efficiently select a subset of rows of a QTableView that match certain criteria? 【发布时间】:2009-09-02 18:51:41 【问题描述】:我有一个QTableView
使用QSqlTableModel
。
在底层数据库(postgresql)表中有一个时间戳列。
如何在选择模型中选择基础时间戳列为 NULL 的所有行?
指向正确方向的指针会有所帮助。
更新:
我遇到的主要问题是性能。我尝试过的每种方法都会导致两个性能问题。
首先是对 selectionModel()->select(selection) 的调用需要 30 秒来处理大约 5,000 条选定记录。它似乎正在为每一行发出选择更改信号。即使信号处理程序被禁用,它仍然需要 10 秒。
第二个性能问题是,即使在使用所选行更新视图之后,尝试滚动视图也非常缓慢且滞后。我的猜测是选择模型由 5,000 个单独的选择组成,而不仅仅是最小数量的选择范围。
在我正在尝试选择的数据中是连续的;因此它应该能够表示为单个选择范围。如果我只是简单地调用tableView->selectAll(),那么这非常快。
我想知道是否有一种规范、有效的方法来选择一堆匹配的行。或者我的代码中可能存在导致性能回归的缺陷。有没有办法按照count0 的建议使用 QSortFilterProxyModel 来完成此任务?我希望视图显示所有行,但选择匹配的行。
这是我尝试的最后一种方法的代码 sn-p:
void MainWindow::selectNullTimestamp()
QModelIndex start = model->index(0, TIMESTAMP_COLUMN);
QModelIndexList indexes = model
->match(start, Qt::DisplayRole,
QVariant(QString("")),
-1,
Qt::MatchFixedString);
QItemSelectionModel* selection_model = ui->tableView->selectionModel();
QItemSelection selection;
foreach(QModelIndex index, indexes)
QModelIndex left =
model->index(index.row(), 0);
QModelIndex right =
model->index(index.row(),
NUM_COLUMNS - 1);
QItemSelection sel(left, right);
selection.merge(sel, QItemSelectionModel::Select);
selection_model->select(selection, QItemSelectionModel::Select);
【问题讨论】:
【参考方案1】:可能为时已晚,但总能帮上忙! 我遇到了这个问题,我认为使用 QItemSelection 可以有效地解决问题
示例:
假设您的表格视图名为 myTableView 并且您想要选择偶数行 [0, 2, 4, 6, ...]
myTableView->clearSelection();
QItemSelection selection;
for (int i = 0 ; i < myTableView->rowCount(); i += 1)
QModelIndex leftIndex = myTableView->model()->index(i, 0);
QModelIndex rightIndex = myTableView->model()->index(i, myTableView->columnCount() -1);
QItemSelection rowSelection(leftIndex, rightIndex);
selection.merge(rowSelection, QItemSelectionModel::Select);
myTableView->selectionModel()->select(selection, QItemSelectionModel::Select);
【讨论】:
而不是 selection.merge(left, right) 使用 selection.append(QItemSelectionRange(leftIndex, rightIndex)) 它提高了性能。【参考方案2】:在模型和视图之间使用 QSortFilterProxyModel。
【讨论】:
我想在视图中显示所有行,并选择匹配的行。使用代理模型是否允许这样做? 代理可以传播选择模型,因此过滤模型中的选择(全选)可以传播到仅选择所需列的其他视图中。 QSortFilterProxyModel 在一列上运行,因此您必须使用它们的管道来选择特定的行。不过,我认为这将是一种优雅的方法。 '...只选择所需的列..'应该是'只选择所需的行..' 谢谢。下周我会试试看。【参考方案3】:为避免混淆,TripsListView 是 QTableView 与 QSqlTableModel 的结合。 这是一种查询方法。至于性能,它只做它必须做的事情。
QModelIndexList indexesAll;
QItemSelection selection;
int i = 0;
QSqlQuery query;
query.exec(qs);
salect = true;
while ( query.next() )
if ( salect )
TripsListView->clearSelection ();
TripsListView->setSelectionMode( QAbstractItemView::MultiSelection );
TripsListView->selectRow(0);
indexesAll = TripsListView->selectionModel()->selectedIndexes ();
salect = false;
for ( i = i; i < TripsModel->rowCount(); i++ )
if ( TripsModel->data(indexesAll[0].sibling(i, 0), Qt::DisplayRole).toInt() == query.value(0).toInt() )
QModelIndex left = TripsModel->index( i, 0 );
// I like this selection code.
QModelIndex right = TripsModel->index( i, 12 );
QItemSelection sel(left, right);
selection.merge(sel, QItemSelectionModel::Select);
break;
if ( salect )
else
TripsListView->clearSelection ();
SearchTripsSelMod->select(selection, QItemSelectionModel::Select);
【讨论】:
【参考方案4】: 您需要确定要选择的行。为此,请遍历整个模型并确定哪些行的时间戳为 NULL。要访问模型的数据,您可以使用QSqlQueryModel::record()
。
您需要创建自定义选择。当前选择由QItemSelectionModel
类表示。您可以通过QAbstractItemView::selectionModel()
和QAbstractItemView::setSelection()
访问表格视图的选择。
为了响应您的代码更新,如果您使用QAbstractItemView::SelectRows
,则可以不使用循环。只需使用您从QAbstractItemModel::match()
收到的选择。
至于速度,请检查发布版本中表格的效率——我知道调试/发布版本的差异对于像您这样的情况很大。如果您使用的是 Qt 4.5,您也会注意到速度有所提升,因为他们确实在该版本中改进了表格等元素。
【讨论】:
QAbstractItemModel 支持一个叫做 match 的函数,它会为你做搜索,并返回一个 QModelIndex 条目列表 酷,我以前从未使用过该功能,但它似乎可以解决第一点。以上是关于如何有效地选择符合某些条件的 QTableView 行的子集?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 QTableView 单元格角落绘制三角形以显示可以从列表中选择的模型数据?