Pyside6 QTableWidget 按列排序 - 正确排序和性能问题

Pyside6 QTableWidget sorting by column - problems with correct sorting and performance

提问人:Lisitrx 提问时间:11/8/2023 更新时间:11/8/2023 访问量:35

问:

我有一个 Pyside6 应用程序,其中包含一个具有 10 列和大约 4000 行的 QTableWidget。当我单击列名称时,我想按单击的列的值对表进行排序。除第一列外,所有列都包含小数点后两位的数字(我知道单元格将它们显示为文本)。

尝试对值进行排序时,我遇到以下问题:

  1. 如果用于排序的列内的数字具有不同的长度(例如 100.00、3500.00、10.00),则排序在不同长度内是正确的,但不会按预期从 0.00 到最大数字进行排序。

  2. 当我的表中有几千行时,排序本身非常慢。在排序过程中,应用程序会冻结,并且在排序完成之前无法使用。这最多可能需要 10 秒。

这是我如何将数据填充到表中的代码:

#Set results df as row in table widget
# Get the current row count
current_row_count = self.table_widget.rowCount()

# Insert a new row at the end
self.table_widget.insertRow(current_row_count)
column_count = 0
#for result in results_list:
for column in results_df:
    current_value = results_df[column].values[0]
    #print("Current value: ", current_value)
    if not column_count == 0:
        table_item = QTableWidgetItem(f"{current_value:.2f}")
    else:
        table_item = QTableWidgetItem(current_value)
    table_item.setFlags(table_item.flags() & ~Qt.ItemIsEditable)
    # Set alignment to center
    table_item.setTextAlignment(Qt.AlignCenter)
    self.table_widget.setItem(current_row_count, column_count, table_item)
    column_count += 1

这是我通过单击列标题对表格进行排序的代码:

self.table_widget.setSortingEnabled(True)
self.table_widget.horizontalHeader().sectionClicked.connect(self.sort_table)

def sort_table(self, column):
    current_order = self.table_widget.horizontalHeader().sortIndicatorOrder()
    if current_order == Qt.AscendingOrder:
       new_order = Qt.DescendingOrder
    else:
       new_order = Qt.AscendingOrder

       self.table_widget.sortItems(column, new_order)

为了解决第一个问题(排序不正确),我尝试使用此代码(使用 setData)以不同的方式填充我的表格,但我只是得到空单元格,我不知道为什么:

#Set results df as row in table widget
# Get the current row count
current_row_count = self.table_widget.rowCount()

# Insert a new row at the end
self.table_widget.insertRow(current_row_count)
column_count = 0
#for result in results_list:
for column in results_df:
    current_value = results_df[column].values[0]
    #print("Current value: ", current_value)
    if not column_count == 0:
        current_value_rounded = round(current_value, 2)
        table_item = QTableWidgetItem()
        table_item.setData(Qt.DisplayRole, current_value_rounded)
    else:
        table_item = QTableWidgetItem(current_value)
    table_item.setFlags(table_item.flags() & ~Qt.ItemIsEditable)
    # Set alignment to center
    table_item.setTextAlignment(Qt.AlignCenter)
    self.table_widget.setItem(current_row_count, column_count, table_item)
    column_count += 1

对于第一个问题: 有人知道为什么第二个代码示例不能使用 setData 来填充我的表吗? 对于第二个问题: 有人知道如何在分拣过程正常工作时加快分拣过程吗?

python 性能 排序 qtablewidget pyside6

评论

0赞 musicamante 11/9/2023
你没有提到一个重要方面:数据类型。我们可以假设这是一个 pandas 数据帧,values() 返回数据的 numpy 表示。这些不是实际的 python 浮点数(或整数),但可能是不同类型的(long、double 等)。更改为 .请注意,如果您有 DataFrame,则在 QTableView 中实现 QAbstractTableModel 子类而不是 QTableWidget 通常更有意义。results_dfcurrent_value_rounded = float(round(current_value, 2))
0赞 Lisitrx 11/9/2023
@musicamante 非常感谢您的回答!你是对的,我忘了指出我正在使用 pandas DataFrame 并想将这些值设置为 TableWidget,对不起。为什么QTableView会是更好的选择,这是由于更好的性能吗?
0赞 musicamante 11/9/2023
好吧,性能取决于很多方面,所以不能绝对保证它会“更快”:虽然 QTableWidget API 是高于普通模型/视图的更高级别的实现(因为它实现了这两个方面),因此有点“笨重”,但它也完全是在 Qt 端实现的,这意味着一旦设置了表格内容, 排序完全是从 C++ 部分完成的,而不是通过 python 瓶颈(这可能是排序要考虑的一个重要方面)。不过,Numpy 数组和 pandas 数据帧的速度非常快,因为它们 »
0赞 musicamante 11/9/2023
» 是专门为在大数据结构中的性能而实现的,如果你不担心保持一致的选择,你可以只在自定义模型上实现,并依靠 pandas/numpy 机制来进行排序,这通常非常快。对与 QAbstractTableModel 一起使用的数据帧(或 numpy 数组)进行一些研究(即使在 SO 上),因为您可以了解许多相关问题和示例。sort()
0赞 ekhumoro 11/9/2023
您是否完全致力于为此使用熊猫?使用Qt的SQL类可以很容易地实现相同的目标(并获得更好的性能)。

答: 暂无答案