奇怪的 QTableWidget 行为 - 并非所有单元格在排序后填充,然后重新填充

Posted

技术标签:

【中文标题】奇怪的 QTableWidget 行为 - 并非所有单元格在排序后填充,然后重新填充【英文标题】:Strange QTableWidget behavior - not all cells populated after sorting followed by repopulating 【发布时间】:2011-10-31 22:25:51 【问题描述】:

我有一个像这样填充的 QTableWidget:

  // Clear the table
  this->topPatchesTableWidget->setRowCount(0);

  this->topPatchesTableWidget->setRowCount(numberToDisplay);
  for(unsigned int pairId = 0; pairId < numberToDisplay; ++pairId)
    
    // Display patch match scores
    QTableWidgetItem* myLabel = new QTableWidgetItem;
    myLabel->setData(Qt::DisplayRole, myValues[pairId]);
    this->tableWidget->setItem(pairId, 0, myLabel);
    ... fill other columns ...
    

(我有一些其他 UI 元素来设置计算 myValues 中的值的属性)。如果我更改属性、重新计算并重新创建表,一切都会按预期工作。如果我通过单击其中一个标题对表格进行排序,则排序正确。但是,如果此时(排序后)我再次单击按钮以重新计算值并重新创建表,则该表非常损坏。也就是说,许多单元格是空的,而不是空的单元格似乎没有任何特定的顺序。

通过添加手动调用

this->tableWidget->sortByColumn(0, Qt::AscendingOrder);

在我的 CreateTable 函数开始时,一切都按预期工作,但当然,新创建的表是按列 0 排序的,而不是最后一次排序时选择的列。

有没有人知道为什么如果不调用 sortByColumn 会出现如此糟糕的情况? (我试图做一个简单的例子,但我无法在演示程序中复制问题)。

谢谢,

大卫

【问题讨论】:

现在有一个关于这个的错误报告:bugreports.qt.io/browse/QTBUG-75479 【参考方案1】:

我在 python 中遇到了类似的问题,如果在该列停止填充后选择了一个列标题以启用对单元格的排序。

我通过在行添加方法的开头设置 self.tableWidget.setSortingEnabled(False) 来解决它,然后在行添加方法的末尾将其设置回 self.tableWidget.setSortingEnabled(True)。根据riverbank computing,这是官方推荐的解决此问题的方法。

QTableWidget.setItem (self, int row, int column, QTableWidgetItem item)

请注意,如果启用了排序(请参阅sortingEnabled)并且column是当前排序列,则该行将移动到由item确定的排序位置。

如果您想设置特定行的多个项目(例如,通过在循环中调用 setItem()),您可能希望在执行此操作之前关闭排序,然后再将其重新打开;这将允许您对同一行中的所有项目使用相同的行参数(即 setItem() 不会移动该行)。

另见 item() 和 takeItem()。

【讨论】:

这个有效,我认为应该是这个问题的答案。使用 PyQt4 在 QTableWidget 上测试。 确实发生了这种情况。我刚刚在 Qt 5.10 中对此进行了测试。 在 5.12.2 中出现同样令人讨厌的行为 :-( 是的,在 5.15.1 中也有同样的奇怪行为。很高兴我找到了这篇文章。我想知道 wtf 继续,现在我知道了。欣赏清晰简洁的信息。马上解决了我的问题。 :)【参考方案2】:

这是对 Karnisov 的回答的详细说明,也适用于 PyQt。在执行任何setItem()s 之前禁用排序也对我有用,但它导致用户的排序选择丢失,所以我这样做了,其中tQTableWidget

oldSort = t.horizontalHeader().sortIndicatorSection()
oldOrder = t.horizontalHeader().sortIndicatorOrder()
t.setSortingEnabled(False)

# make the changes

t.sortItems(oldSort, oldOrder)
t.setSortingEnabled(True)

请注意,此代码仍可能对排序进行轻微更改。这似乎是因为 Qt 在这里使用的排序不会移动任何已经按顺序排列的项目,所以如果我们有一个这样的表:

NUMBER    LETTER    OTHER LETTER
     1         B               C
     2         G               Q
     3         A               Q

如果我们按 NUMBER 排序,然后按 OTHER LETTER,则没有任何变化。但如果我们按 LETTER 排序,然后按 OTHER LETTER,我们会得到:

NUMBER    LETTER    OTHER LETTER
     1         B               C
     3         A               Q
     2         G               Q

因此,如果我们之前先按 LETTER 排序,然后按 OTHER LETTER,这段代码只会按 OTHER LETTER 进行一次排序,我们最终会得到第二个版本的表格而不是第一个(假设顺序元素已添加到匹配 NUMBER 的表中)。在我的代码中的这个位置,所有项目都被删除并重新添加以刷新表格,因此这有时会导致顺序发生明显变化。

【讨论】:

【参考方案3】:

我遇到了同样的问题 - 总是,当我想插入新数据时,我会构建标题和 setSortingEnabled(true)。我猜 QTableWidget 不喜欢多次调用setSortingEnabled(true)。所以我把它放到了我的 MainWindown 的构造函数中,就这样!

【讨论】:

【参考方案4】:

我从来没有弄清楚这有什么问题。我放弃并实现了一个自定义模型/视图,无论如何这可能是一个更好的主意。

【讨论】:

Karnisov 为这个问题提供了更好的答案。我认为您应该回来并选择他的解决方案。

以上是关于奇怪的 QTableWidget 行为 - 并非所有单元格在排序后填充,然后重新填充的主要内容,如果未能解决你的问题,请参考以下文章

双重比较的C ++非常奇怪的行为[关闭]

UIView ExclusiveTouch:UIBarButtonItem 的奇怪行为

让 Enter 键的行为类似于 QTableWidget 中的 Tab

`const char *` 在库 .so 文件中存储的奇怪行为

将 UIScrollView 滚动到键盘隐藏的 UITextView 中的奇怪行为

QTableWidget 扩展列以填充最后一列固定宽度