首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对QTreeWidget列进行排序?

如何对QTreeWidget列进行排序?
EN

Stack Overflow用户
提问于 2021-03-23 23:50:47
回答 1查看 58关注 0票数 0

我有一个小的用户界面,我正在使用QTreeWidget,它包含4列‘文件夹’,‘文件名’,‘大小’,‘所有者’现在当我点击‘大小’列排序,它没有按正确的顺序排序(B,Kib和Mib),因为'Size‘的值是在字符串中它只排序第一个数字和混合所有字节,Kib和Mib。

如果列同时包含int和string两种类型,谁能指导我们以正确的顺序进行排序?

代码语言:javascript
复制
from PyQt5.QtWidgets import *


class TestUI(QWidget):
    def __init__(self):
        super(TestUI, self).__init__(parent=None)

        self.setGeometry(10, 10, 700, 350)
        self.setWindowTitle('Runner up !')
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.tree_widget = QtGui.QTreeWidget()
        self.tree_widget.setSelectionMode(QtGui.QTreeWidget.ExtendedSelection)
        headers = ['Folder', 'Filepath', 'Size', 'Owner']
        self.tree_widget.setHeaderLabels(headers)
        self.tree_widget.setSortingEnabled(True)

        metadata = {'Desktop': [('/u/donald/Desktop/file_test.txt', '2 MiB', 'Donald'),
                                ('/u/donald/Desktop/file_test_01.txt', '20 KiB', 'Donald')]}

        for folder, folderdata in metadata:
            top_item = QtGui.QTreeWidgetItem(self.tree_widget,
                                     [folder, '', '', ''])
            for data in folderdata:
                filepath, size, owner = data[0], data[1], data[2]

                child_item = QtGui.QTreeWidgetItem(top_item, ['', filepath, size, owner])


if __name__ == '__main__':
    app = QApplication(sys.argv)
    WIN = TestUI()
    WIN.show()
    app.exec_()

它看起来像这样

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-24 00:13:19

Qt不知道它们是文件大小,而是字符串,所以它将它们与这些规则进行比较。因此,如果您想要自定义排序,则必须覆盖QTreeWidgetItem的__lt__方法。为了进行比较,您可以进行一个映射,将单位转换为可以比较的数字,但是为了避免这项工作,我更喜欢使用这样一个库:datasize (python -m pip install datasize)

代码语言:javascript
复制
from datasize import DataSize

SIZE_COLUMN = 2


class TreeWidgetItem(QtGui.QTreeWidgetItem):
    def __lt__(self, other):
        column = self.treeWidget().sortColumn()
        if column == SIZE_COLUMN:
            # DataSize does not accept space between the quantity and the unit,
            # so we eliminate the spaces:
            text_with_spaces = self.text(column).replace(" ", "")
            other_text_with_spaces = other.text(column).replace(" ", "")
            return DataSize(text_with_spaces) < DataSize(other_text_with_spaces)
        return super(TreeWidgetItem, self).__lt__(other)
代码语言:javascript
复制
for filepath, size, owner in folderdata:
    child_item = TreeWidgetItem(top_item, ["", filepath, size, owner])

如果你不想使用datasize,那么你必须实现你自己的转换器,就像这样(有关其他示例,请参阅Python - Parse human-readable filesizes into bytes ):

代码语言:javascript
复制
SIZE_COLUMN = 2
SIZE_MAPPING = {"MiB": 2 ** 20, "KiB": 2 ** 10}


def converter(text):
    string_value, unit = text.split()
    return float(string_value) * SIZE_MAPPING[unit]


class TreeWidgetItem(QtGui.QTreeWidgetItem):
    def __lt__(self, other):
        column = self.treeWidget().sortColumn()
        if column == SIZE_COLUMN:
            return converter(self.text(column)) < converter(other.text(column))
        return super().__lt__(other)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66766643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档