Qtableview indexAt 不同的行为 with/without header
Qt TableView indexAt different behaviour with/without header
使用 PySide 1.2
在 QTableView
returns 中抓取点击项目的索引,无论是否存在水平 header 都会产生不同的结果。
如果有横的header,好像也算在visualRect
里面了。所以第一行第一列索引不再是 0, 0 而是 1, 0.
这是故意的吗?因为它真的很混乱和不方便,因为最后一行索引将无效。
重现:
import re
import operator
import os
import sys
# from Qt.QtCore import *
# from Qt.QtGui import *
# from Qt.QtWidgets import *
from PySide.QtCore import *
from PySide.QtGui import *
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class CustomTableView(QTableView):
"""
"""
def __init__(self, parent=None):
"""
"""
super(CustomTableView, self).__init__(parent=parent)
def mousePressEvent(self, mouse_event):
"""
"""
view_pos = self.mapFromGlobal(mouse_event.globalPos())
index = self.indexAt(view_pos)
print('mouse press index not cutting header : ' + str((index.row(), index.column())))
view_pos.setY(view_pos.y() - self.horizontalHeader().sizeHint().height())
index = self.indexAt(view_pos)
print('mouse press index cutting header : ' + str((index.row(), index.column())))
super(CustomTableView, self).mousePressEvent(mouse_event)
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create table
self.get_table_data()
table = self.createTable()
# layout
layout = QVBoxLayout()
layout.addWidget(table)
self.setLayout(layout)
def get_table_data(self):
stdouterr = os.popen4("dir c:\")[1].read()
lines = stdouterr.splitlines()
lines = lines[5:]
lines = lines[:-2]
self.tabledata = [re.split(r"\s+", line, 4)
for line in lines]
def createTable(self):
# create the view
tv = CustomTableView()
# set the table model
header = ['date', 'time', '', 'size', 'filename']
tm = MyTableModel(self.tabledata, header, self)
tv.setModel(tm)
return tv
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, headerdata, parent=None, *args):
""" datain: a list of lists
headerdata: a list of strings
"""
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain
self.headerdata = headerdata
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return None
elif role != Qt.DisplayRole:
return None
return self.arraydata[index.row()][index.column()]
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.headerdata[col]
return None
if __name__ == "__main__":
main()
您不必使用全局位置然后将其传递给本地位置,因为您将获得相对于 QTableView 上角的位置,但 indexAt 需要相对于内容的位置根据docs:
PySide.QtGui.QAbstractItemView.indexAt(point)
Parameters: point – PySide.QtCore.QPoint
Return type: PySide.QtCore.QModelIndex
Returns the model index of the item at the viewport coordinates point
.
您必须使用事件的位置:mouse_event.pos()
def mousePressEvent(self, mouse_event):
index = self.indexAt(mouse_event.pos())
print('mouse press index: ' + str((index.row(), index.column())))
super(CustomTableView, self).mousePressEvent(mouse_event)
如果要使用全局位置,则必须将其转换为相对于 viewport()
:
的本地位置
def mousePressEvent(self, mouse_event):
view_pos = self.viewport().mapFromGlobal(mouse_event.globalPos())
index = self.indexAt(view_pos)
print('mouse press index : ' + str((index.row(), index.column())))
super(CustomTableView, self).mousePressEvent(mouse_event)
使用 PySide 1.2
在 QTableView
returns 中抓取点击项目的索引,无论是否存在水平 header 都会产生不同的结果。
如果有横的header,好像也算在visualRect
里面了。所以第一行第一列索引不再是 0, 0 而是 1, 0.
这是故意的吗?因为它真的很混乱和不方便,因为最后一行索引将无效。
重现:
import re
import operator
import os
import sys
# from Qt.QtCore import *
# from Qt.QtGui import *
# from Qt.QtWidgets import *
from PySide.QtCore import *
from PySide.QtGui import *
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class CustomTableView(QTableView):
"""
"""
def __init__(self, parent=None):
"""
"""
super(CustomTableView, self).__init__(parent=parent)
def mousePressEvent(self, mouse_event):
"""
"""
view_pos = self.mapFromGlobal(mouse_event.globalPos())
index = self.indexAt(view_pos)
print('mouse press index not cutting header : ' + str((index.row(), index.column())))
view_pos.setY(view_pos.y() - self.horizontalHeader().sizeHint().height())
index = self.indexAt(view_pos)
print('mouse press index cutting header : ' + str((index.row(), index.column())))
super(CustomTableView, self).mousePressEvent(mouse_event)
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create table
self.get_table_data()
table = self.createTable()
# layout
layout = QVBoxLayout()
layout.addWidget(table)
self.setLayout(layout)
def get_table_data(self):
stdouterr = os.popen4("dir c:\")[1].read()
lines = stdouterr.splitlines()
lines = lines[5:]
lines = lines[:-2]
self.tabledata = [re.split(r"\s+", line, 4)
for line in lines]
def createTable(self):
# create the view
tv = CustomTableView()
# set the table model
header = ['date', 'time', '', 'size', 'filename']
tm = MyTableModel(self.tabledata, header, self)
tv.setModel(tm)
return tv
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, headerdata, parent=None, *args):
""" datain: a list of lists
headerdata: a list of strings
"""
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain
self.headerdata = headerdata
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return None
elif role != Qt.DisplayRole:
return None
return self.arraydata[index.row()][index.column()]
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.headerdata[col]
return None
if __name__ == "__main__":
main()
您不必使用全局位置然后将其传递给本地位置,因为您将获得相对于 QTableView 上角的位置,但 indexAt 需要相对于内容的位置根据docs:
PySide.QtGui.QAbstractItemView.indexAt(point)
Parameters: point – PySide.QtCore.QPoint
Return type: PySide.QtCore.QModelIndex
Returns the model index of the item at the
viewport coordinates point
.
您必须使用事件的位置:mouse_event.pos()
def mousePressEvent(self, mouse_event):
index = self.indexAt(mouse_event.pos())
print('mouse press index: ' + str((index.row(), index.column())))
super(CustomTableView, self).mousePressEvent(mouse_event)
如果要使用全局位置,则必须将其转换为相对于 viewport()
:
def mousePressEvent(self, mouse_event):
view_pos = self.viewport().mapFromGlobal(mouse_event.globalPos())
index = self.indexAt(view_pos)
print('mouse press index : ' + str((index.row(), index.column())))
super(CustomTableView, self).mousePressEvent(mouse_event)