【发布时间】:2014-02-23 20:14:10
【问题描述】:
所以我有一个 QTableView,我只想让列排序在第 1 列而不是第 2 列。
当然,我尝试在QHeaderView 或QTableView 上installEventFilter,但除非您在QApplication 上installEventFilter,否则MouseButtonPress 事件不会被传递
现在,如果在调用 eventFilter 时,目标 object 始终是顶级小部件,尽管 event.pos() 实际上与标题或表格单元格相关,具体取决于您单击的位置。
所以我们不能使用QHeaderView.rect().contains(event.pos()) 来判断用户是否点击了标题,因为当您点击第一个表格单元格的顶部边缘时会出现误报。
但是,您仍然可以使用 globalPos 进行计算,但是当您更改布局或在 tableview 上方添加更多小部件时,您的 eventFilter 的逻辑必须更改。
我认为 event.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_())
【问题讨论】:
标签: qt pyqt pyqt4 qtableview qt4.8