pyqt qt4 QTableView如何禁用某些列的排序? [英] pyqt qt4 QTableView how to disable sorting for certain columns?

查看:225
本文介绍了pyqt qt4 QTableView如何禁用某些列的排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个QTableView,我只想让列在第1列而不是在column2上进行排序.

So I have a QTableView and I only want to let column sorting on column 1 but not column2.

自然,我尝试在QHeaderViewQTableView上使用installEventFilter,但是除非您在QApplication上使用installEventFilter

Naturally I tried to installEventFilter on QHeaderView or QTableView, but MouseButtonPress event is not being passed unless you installEventFilter on QApplication

现在,如果调用eventFilter时,则目标object始终是顶级窗口小部件,尽管event.pos()实际上是相对于标题或表单元格的,具体取决于您单击的位置.

Now if when eventFilter is called, the target object is always the top level widget although event.pos() is actually relative to the header or tablecell depending on where you click.

因此,我们无法使用QHeaderView.rect().contains(event.pos())来确定用户是否单击标题,因为单击第一个表格单元格的顶部边缘时您会得到误报.

So we cannot use QHeaderView.rect().contains(event.pos()) to find out if the user clicks on the header because you get false positive when you click on the top edge of the very first table cell.

不过,您仍然可以使用globalPos进行计算,但是当您更改布局或在表格视图上方添加更多小部件时,eventFilter的逻辑必须更改.

You can still however calculate this using globalPos but then your eventFilter's logic has to change when you change layout or add more widgets above the tableview.

我相信event.pos()返回相对pos是一个错误,即使object参数始终引用相同的顶级小部件.

I believe it is a bug that event.pos() returns the relative pos even the object argument always refer to the same top level widget.

更合乎逻辑的API是,有一个event.target()方法可返回目标,以在此目标中计算相对位置.

A more logical API would be that there is a event.target() method to return the target where it calculates the relative pos.

但是我没有看到target()方法或在此事件过滤器中找到目标的方法.

But I don't see a target() method or a way to find the target in this event filter.

也许我想念什么?

# -*- coding: utf-8 -*-
# pyqt windows 4.10.3
# python 2.7.5 32 bits
from PyQt4.QtCore import *
from PyQt4.QtGui import *

app = None
tableHeader = None

class MyModel(QAbstractTableModel):
    def rowCount(self, QModelIndex_parent=None, *args, **kwargs):
        return 2

    def columnCount(self, QModelIndex_parent=None, *args, **kwargs):
        return 2

    def data(self, modelIndex, role=None):
        if modelIndex.isValid():
            row = modelIndex.row()
            col = modelIndex.column()
            if role == Qt.DisplayRole:
                return "%02d,%02d" % (row, col)

    def flags(self, index):
        if index.isValid():
            return Qt.ItemIsEnabled

    def headerData(self, section, Qt_Orientation, role=None):
        if role == Qt.DisplayRole and Qt_Orientation == Qt.Horizontal:
            return "Column " + str(section+1)

class MyEventFilter(QObject):
    def eventFilter(self, object, event):
        if event.type() == QEvent.MouseButtonPress:
            # object is always app/top level widget
            print 'MouseButtonPress target :' + repr(object)
            # even though event.pos() gives pos relative to the header when you click on header,
            # and pos relative to table cells when you click on table cell
            print repr(event.pos())
            # however we can get the mouse's global position
            print repr(event.globalPos())
            # given the top level widget's geometry
            print repr(app.activeWindow().geometry())
            # and the table header's left, top and height
            print repr(tableHeader.rect())
            # we can find out whether mouse click is targeted at the header
            print repr(event.globalPos().y() - app.activeWindow().geometry().y())
            # BUT WHAT IF THE LAYOUT CHANGE OR WE ADD MORE WIDGETS ABOVE THE TABLEVIEW?
            # WE HAVE TO ADJUST THE CALCULATION ABOVE!
        return False


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    w = QMainWindow()
    t = QTableView()
    tableHeader = t.horizontalHeader()
    t.setModel(MyModel())
    w.setCentralWidget(t)
    ef = MyEventFilter()
    # installing in QMainWindow or QTableView won't catch MouseButtonPress
    # https://qt-project.org/forums/viewthread/9347
    #w.installEventFilter(ef)
    #t.installEventFilter(ef)
    app.installEventFilter(ef)
    w.show()
    sys.exit(app.exec_())

推荐答案

有一个更简单的解决方案:重新实现

There's a much easier solution: reimplement the sort method of the model, and only permit sorting for the appropriate column.

此外,作为一种改进,请使用 sortIndicatorChanged 标头的信号,以在适当时恢复当前的排序指示器.

Also, as an added refinement, use the sortIndicatorChanged signal of the header to restore the current sort indicator when appropriate.

这是一个演示脚本:

from PyQt4 import QtGui, QtCore

class TableModel(QtGui.QStandardItemModel):
    _sort_order = QtCore.Qt.AscendingOrder

    def sortOrder(self):
        return self._sort_order

    def sort(self, column, order):
        if column == 0:
            self._sort_order = order
            QtGui.QStandardItemModel.sort(self, column, order)

class Window(QtGui.QWidget):
    def __init__(self, rows, columns):
        QtGui.QWidget.__init__(self)
        self.table = QtGui.QTableView(self)
        model = TableModel(rows, columns, self.table)
        for row in range(rows):
            for column in range(columns):
                item = QtGui.QStandardItem('(%d, %d)' % (row, column))
                item.setTextAlignment(QtCore.Qt.AlignCenter)
                model.setItem(row, column, item)
        self.table.setModel(model)
        self.table.setSortingEnabled(True)
        self.table.horizontalHeader().sortIndicatorChanged.connect(
            self.handleSortIndicatorChanged)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.table)

    def handleSortIndicatorChanged(self, index, order):
        if index != 0:
            self.table.horizontalHeader().setSortIndicator(
                0, self.table.model().sortOrder())

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window(5, 5)
    window.show()
    window.setGeometry(600, 300, 600, 250)
    sys.exit(app.exec_())

这篇关于pyqt qt4 QTableView如何禁用某些列的排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆