【问题标题】:QtableView sortingEnabled and column selectionQtableView sortingEnabled 和列选择
【发布时间】:2021-11-09 06:56:41
【问题描述】:

我在 PySide 6 中使用 QtableView,由 QSortFilterProxyModel 填充,并且 setSortingEnabled 为 true,因此我可以按列排序。 但是通过这样做,我不再能够通过单击标题来选择列。

这个想法是能够通过单击箭头图标对列进行排序,并通过单击文本来选择列。

【问题讨论】:

    标签: python select qtableview qsortfilterproxymodel pyside6


    【解决方案1】:

    启用sortingEnabled属性后,selectColumn槽的sectionPressed信号断开,因此可能的解决方案是重新连接:

    from PySide6.QtCore import QSortFilterProxyModel
    from PySide6.QtGui import QStandardItem, QStandardItemModel
    from PySide6.QtWidgets import QApplication, QTableView
    
    
    def main():
        app = QApplication()
    
        model = QStandardItemModel(10, 4)
        for i in range(model.rowCount()):
            for j in range(model.columnCount()):
                item = QStandardItem(f"item {i}x{j}")
                model.setItem(i, j, item)
    
        proxy_model = QSortFilterProxyModel()
        proxy_model.setSourceModel(model)
    
        view = QTableView()
        view.setSortingEnabled(True)
        view.setModel(proxy_model)
        view.resize(640, 480)
        view.show()
    
        view.horizontalHeader().sectionPressed.connect(view.selectColumn)
    
        app.exec()
    
    
    if __name__ == "__main__":
        main()
    

    既然OP希望它只在指示器被按下时被排序,那么就需要防止命令指示器在被按下时改变状态。

    from PySide6.QtCore import QSortFilterProxyModel, Qt
    from PySide6.QtGui import QStandardItem, QStandardItemModel
    from PySide6.QtWidgets import QApplication, QHeaderView, QTableView
    
    
    class HorizontalHeader(QHeaderView):
        def mousePressEvent(self, event):
            self.new_order = self.sortIndicatorOrder()
            super().mousePressEvent(event)
            height = self.height()
            x = event.position().x()
            logical_index = self.logicalIndexAt(x)
            x_left = self.sectionPosition(logical_index)
            x_right = x_left + self.sectionSize(logical_index)
            if (x_right - height) <= x <= x_right:
                self.new_order = (
                    Qt.DescendingOrder
                    if self.new_order == Qt.AscendingOrder
                    else Qt.AscendingOrder
                )
    
        def mouseReleaseEvent(self, event):
            super().mouseReleaseEvent(event)
            x = event.position().x()
            logical_index = self.logicalIndexAt(x)
            self.setSortIndicator(logical_index, self.new_order)
    
    
    def main():
        app = QApplication()
        app.setStyle("fusion")
    
        model = QStandardItemModel(10, 4)
        for i in range(model.rowCount()):
            for j in range(model.columnCount()):
                item = QStandardItem(f"item {i}x{j}")
                model.setItem(i, j, item)
    
        proxy_model = QSortFilterProxyModel()
        proxy_model.setSourceModel(model)
    
        view = QTableView()
        horizontal_header = HorizontalHeader(Qt.Horizontal)
        view.setHorizontalHeader(horizontal_header)
        horizontal_header.setSortIndicatorShown(True)
        horizontal_header.setSectionsClickable(True)
        view.setModel(proxy_model)
        horizontal_header.sortIndicatorChanged.connect(proxy_model.sort)
        horizontal_header.setSortIndicator(0, Qt.AscendingOrder)
        view.resize(640, 480)
        view.show()
    
        app.exec()
    
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

    • 非常好,该列是可选择的,但只要我点击标题,它也会被排序。单击箭头图标时是否可以限制排序,或者另一种解决方案可能是不使用代理模型并通过右键单击列标题来实现排序?
    • @EricRV 尝试新的解决方案
    • 是的,它运作良好。您的代码中没有标题,所以我添加了标题数据 (model.setHeaderData(0, Qt.Horizo​​ntal, "Serial Number" ),是的,它很完美!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2019-03-17
    • 2020-09-29
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 2011-04-21
    相关资源
    最近更新 更多