如何使QTreeView始终首先对某个类别的项目进行排序



我想在QTreeView中显示"文件夹"one_answers"文件"。文件夹意味着能够包含文件,由于这种关系,我希望文件夹项目显示在树视图中的文件项目上方。视图应该是可排序的。如何确保文件夹项目始终显示在树视图中的文件项目上方?

下面的代码提供了一个带有文件夹和文件项的树状视图示例:

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

def _create_item(text, is_folder):
    item = QStandardItem(text)
    item.setData(is_folder, Qt.UserRole)
    return item

def _folder_row(name, date):
    return [_create_item(text, True) for text in (name, date)]

def _file_row(name, date):
    return [_create_item(text, False) for text in (name, date)]

class _Window(QMainWindow):
    def __init__(self):
        super().__init__()
        widget = QWidget()
        self.__view = QTreeView()
        layout = QVBoxLayout(widget)
        layout.addWidget(self.__view)
        self.setCentralWidget(widget)
        model = QStandardItemModel()
        model.appendRow(_file_row('File #1', '01.09.2014'))
        model.appendRow(_folder_row('Folder #1', '01.09.2014'))
        model.appendRow(_folder_row('Folder #2', '02.09.2014'))
        model.appendRow(_file_row('File #2', '03.09.2014'))
        model.setHorizontalHeaderLabels(['Name', 'Date'])
        self.__view.setModel(model)
        self.__view.setSortingEnabled(True)

app = QApplication([])
w = _Window()
w.show()
app.exec_()

一个解决方案是将模型包装在QSortFilterProxyModel中,并重新实现代理的lessThan方法,使其使文件夹项始终位于文件项之前:

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

def _create_item(text, is_folder):
    item = QStandardItem(text)
    item.setData(is_folder, Qt.UserRole)
    return item

def _folder_row(name, date):
    return [_create_item(text, True) for text in (name, date)]

def _file_row(name, date):
    return [_create_item(text, False) for text in (name, date)]

class _SortProxyModel(QSortFilterProxyModel):
    """Sorting proxy model that always places folders on top."""
    def __init__(self, model):
        super().__init__()
        self.setSourceModel(model)
    def lessThan(self, left, right):
        """Perform sorting comparison.
        Since we know the sort order, we can ensure that folders always come first.
        """
        left_is_folder = left.data(Qt.UserRole)
        left_data = left.data(Qt.DisplayRole)
        right_is_folder = right.data(Qt.UserRole)
        right_data = right.data(Qt.DisplayRole)
        sort_order = self.sortOrder()
        if left_is_folder and not right_is_folder:
            result = sort_order == Qt.AscendingOrder
        elif not left_is_folder and right_is_folder:
            result = sort_order != Qt.AscendingOrder
        else:
            result = left_data < right_data
        return result

class _Window(QMainWindow):
    def __init__(self):
        super().__init__()
        widget = QWidget()
        self.__view = QTreeView()
        layout = QVBoxLayout(widget)
        layout.addWidget(self.__view)
        self.setCentralWidget(widget)
        model = QStandardItemModel()
        model.appendRow(_file_row('File #1', '01.09.2014'))
        model.appendRow(_folder_row('Folder #1', '01.09.2014'))
        model.appendRow(_folder_row('Folder #2', '02.09.2014'))
        model.appendRow(_file_row('File #2', '03.09.2014'))
        model.setHorizontalHeaderLabels(['Name', 'Date'])
        proxy_model = _SortProxyModel(model)
        self.__view.setModel(proxy_model)
        self.__view.setSortingEnabled(True)

app = QApplication([])
w = _Window()
w.show()
app.exec_()

相关内容

  • 没有找到相关文章

最新更新