pyqt qt4 QTableView如何禁用某些列的排序?

2023-11-26

所以我有一个 QTableView,我只想让列排序在第 1 列而不是第 2 列。

自然地我尝试installEventFilter on QHeaderView or QTableView, but MouseButtonPress事件不会被传递,除非你installEventFilter on QApplication

现在如果什么时候eventFilter被称为,目标object虽然始终是顶级小部件event.pos()实际上是相对于标题或表格单元格的,具体取决于您单击的位置。

所以我们不能使用QHeaderView.rect().contains(event.pos())查明用户是否单击标题,因为当您单击第一个表格单元格的上边缘时会出现误报。

但是,您仍然可以使用 globalPos 来计算此值,但是当您更改布局或在表视图上方添加更多小部件时,您的 eventFilter 的逻辑必须更改。

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

一个更合乎逻辑的 API 是有一个 event.target() 方法来返回计算相对位置的目标。

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

也许我错过了什么?

# -*- 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_())

有一个更简单的解决方案:重新实现sort模型的方法,并且只允许对适当的列进行排序。

另外,作为额外的改进,使用排序指示符已更改标头信号在适当时恢复当前排序指示器。

这是一个演示脚本:

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_())
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pyqt qt4 QTableView如何禁用某些列的排序? 的相关文章

随机推荐

  • 如何通过库名称找到库的文件名?

    如何通过库名称找到库的文件名 换句话说 当我使用 lc 时 我知道它是 lib libc so 6 或类似的东西 我希望能够键入一些命令 其中 lc 是输入 lib 是 libc so 6 是输出 为了进一步扩展这个想法 我想指定我自己的搜
  • 用于扫描可用 Wi-Fi 网络的 iOS API 是什么

    这就是问题所在 但这是一个长版本 我正在开发一个需要模仿 Belkin WeMo 的连接工作流程的项目 WeMo 是一个可以通过 iOS 应用程序控制的物理开关 设置的工作原理如下 WeMo 充当 Wi Fi 路由器 它会广播 SSID 而
  • Spring 4 MVC - Rest服务 - 在bean中使用默认值

    我在用Spring 4 1 4并实现一个简单的REST服务 我确实有一个POST方法得到一个Person对象作为请求 ResponseStatus value HttpStatus CREATED RequestMapping value
  • Google 容器引擎中的 Kubernetes HTTPS 入口

    我想公开在 Google Container Engine 中运行的 HTTP 服务仅 HTTPS负载平衡器 如何在入口对象中定义我想要的HTTPS仅负载均衡器而不是默认 HTTP 或者有什么办法可以永久删除HTTP来自创建的负载均衡器的协
  • Xcode 4 中的“运行 > 在 Objective-C 异常时停止”?

    也许有人知道 Xcode 4 中的 运行 gt 在 Objective C 异常时停止 菜单在哪里 我有时在 Xcode 3 中使用过它 但它在新的 IDE 中消失了 在xcode 4的左侧栏中 点击断点选项卡 第 6 个 选项卡结束 点击
  • 如何让 Maven 2 构建 2 个独立的 WAR 文件

    当做一个mvn install我想在我的目标目录中得到 2 个 WAR 文件 其中一个将包含生产 web xml另一个将包含test uat web xml 我试过这个
  • 我如何运行 Conda?

    我安装了 Anaconda 并且可以运行 Python 所以我假设我安装正确 按照此介绍性文档 我正在尝试安装 Python v3 3 因此我将以下行复制并粘贴到我的控制台中 conda create n py33 python 3 3 a
  • 将VC++的__try/__ except EXCEPTION_STACK_OVERFLOW移植到MinGW

    我正在尝试使用 VC 的 try except 语句将一些代码移植到 MinGW bool success true try except EXCEPTION STACK OVERFLOW GetExceptionCode EXCEPTIO
  • 通过 IdeaVim 在 IntelliJ 中使用 Vim 插件

    有没有办法通过 IdeaVim 在 IntelliJ 中使用 Vim 插件 在这种情况下 我正在寻找一种使用 easymotion Vim 插件的方法 您可以使用acejump插件或emacsIDEAs 不要被它的名字吓到 它只是介绍了 a
  • 使用 Pandas 从另一个数据帧中删除一个数据帧

    我有两个不同大小的数据框 df1 nad df2 我想从中删除df1存储在其中的所有行df2 所以如果我有df2等于 A B 0 wer 6 1 tyu 7 And df1等于 A B C 0 qwe 5 a 1 wer 6 s 2 wer
  • 删除R中tmap中的图例

    我有一个简单的问题 如何删除 R 中 tmap 中自动添加的图例 在这种情况下 我想删除右侧描述 级别 的图例 这是我尝试过的 tm shape densities polygons tm polygons col level palett
  • matlab:将向量划分为固定大小的重叠块

    我有一个向量 我想将其拆分为大小重叠的子向量cs轮流在sh 想象输入向量是 v 1 2 3 4 5 6 7 8 9 10 11 12 13 A 1 13 given a chunksize of 4 cs 4 和 2 sh 2 结果应如下所
  • 调用未定义函数curl_init()错误

    我在 Win 64 位操作系统 php 5 6 8 上使用 Eclipse PDT 来开发 PHP 我遇到过 Call to undefined function curl init 错误 我删除了 前extension php curl
  • D3D11:如何绘制简单的像素对齐线?

    我尝试用 D3D11 在两个顶点之间画一条线 我在 D3D9 和 D3D11 中有一些经验 但在 D3D11 中绘制一条线 从一个给定像素开始并以另一个像素结束 似乎是一个问题 我做了什么 我向每个顶点的像素坐标添加了 0 5f 以适应纹素
  • CakePHP如何通过ID数组获取多行

    我想根据 ID 数组列表从数据库中提取多行 在其他一些框架中似乎有类似 WHERE IN 的东西 但这里没有 有人可以告诉我该怎么做吗 我想知道如何通过 find 或 read 或任何其他 cakephp 函数 来做到这一点 而不是手动构建
  • Rails 库包括

    关于 lib 目录中定义的模块 我有一个令人费解的问题 我有两个文件 lib authentication rb module Authentication end lib test module rb module TestModule
  • HttpServlet 类与 Jersey 一起使用之间的混淆

    我正在构建实现 RESTful API 的 servlet 我知道 Jersey 是一个用于破译和使用给定 URL 的框架 我如何将它与HttpServlet class 我不明白两者如何相互合作 我想这是一个非常笼统的问题 但我已经阅读了
  • Python google Drive API下载,文件在哪里?

    我使用此处找到的 python 代码在谷歌驱动器上下载文件 https developers google com drive v3 web manage downloads我有这个范围 https www googleapis com a
  • GridView.scrollTo() 的解决方法?

    如上所述here Android的GridView scrollTo 不起作用 解决方案提到的方法 setSelectedPosition 似乎不存在于GridView smoothScrollToPosition确实有效 但我真的不想要动
  • pyqt qt4 QTableView如何禁用某些列的排序?

    所以我有一个 QTableView 我只想让列排序在第 1 列而不是第 2 列 自然地我尝试installEventFilter on QHeaderView or QTableView but MouseButtonPress事件不会被传