所以我有一个 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_())