如何有效地选择符合某些条件的 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的选定行获取值?

如何在 QTableView 单元格角落绘制三角形以显示可以从列表中选择的模型数据?

在浮子上施加(某些情况下)周期性边界条件的有效方法?

pyqt qt4 QTableView 如何禁用某些列的排序?

excel如何根据条件自动变换行列颜色?

如何禁用 QtableView pyqt 中的某些列?