[PyQt] Strange behaviour of key_return
Kamp, Peter van der (IMARES)
peter.vanderkamp at wur.nl
Thu Apr 5 13:47:52 BST 2012
Hello,
In my application I have a tableview in which the user must be able to scroll through the (editable) cells by using Tab, Key_right and Return. Columns that are disabled must be skipped. When the lower right cell is reached, a new row must be created when one of the before mentioned keys is pressed. To implement this, I reimplemented QTableView and the event and keyPressEvent event handlers. This works OK in a 'non-graphics' mode i.e. QTableView is not 'painted' in a QGraphicsView. In this case, pressing one of the keys results in moving the cursor to the next cell or row.
As soon as the tableview is part of an QGraphicsView, pressing Return results in moving the cursor to the end of the row. This is due to the fact that event is called twice for a single Return press. It is unclear to me why this is happening. Anyone any ideas? I enclose the code. Calling main() runs the code in 'non-graphics' mode, calling maing() runs it in 'graphics' mode.
Python v. 2.6.5
PyQt v. 4.6.2
Peter
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import PyQt4.QtCore
from PyQt4 import QtCore
from PyQt4 import QtGui
import sys
my_array = [[1, "m", 12.0, 3.0], [2, "f", 10.0, 11.0]]
def maing():
app = QApplication(sys.argv)
scene = QtGui.QGraphicsScene()
scene.setSceneRect(0,0,300,200)
view = QtGui.QGraphicsView()
view.setScene(scene)
view.show()
w = MyWindow()
t = scene.addWidget(w)
layout = QtGui.QGraphicsLinearLayout()
layout.addItem(t)
# w.show()
sys.exit(app.exec_())
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QTableView):
def __init__(self, *args):
QTableView.__init__(self, *args)
self.tablemodel = MyTableModel(my_array, self)
self.setModel(self.tablemodel)
self.setItemDelegate(MyDelegate(self))
hh = self.horizontalHeader()
hh.setStretchLastSection(True)
self.resizeColumnsToContents()
def event(self, event):
if (event.type() == QtCore.QEvent.ShortcutOverride) and \
((event.key() == QtCore.Qt.Key_Tab) or (event.key() == QtCore.Qt.Key_Return)):
print "Type: ", event.type()
print "In event", id(event)
end = self.endOfTable()
if end:
self.insertRow()
if (event.key() == QtCore.Qt.Key_Return):
self.toNextCellOrRow()
return True
else:
return super(MyWindow, self).event(event)
def keyPressEvent(self, event):
if (event.type() == QtCore.QEvent.KeyPress) and (event.key() == QtCore.Qt.Key_Right):
end = self.endOfTable()
print "in keypress"
if end:
self.insertRow()
self.toNextCellOrRow()
else:
return super(MyWindow, self).keyPressEvent(event)
def insertRow(self):
nr_rows = self.tablemodel.rowCount()
self.tablemodel.beginInsertRows(QtCore.QModelIndex(),nr_rows, nr_rows)
self.tablemodel.endInsertRows()
my_array.append([9, "f", 99.0, 99.0])
def toNextCellOrRow(self):
section = self.currentIndex().column()
current_row = self.currentIndex().row()
#nr_rows = self.tablemodel.rowCount()
cursor_index = self.moveCursor(QAbstractItemView.MoveRight, Qt.NoModifier)
if (section == cursor_index.column()):
index = self.tablemodel.createIndex(cursor_index.row()+1, 0)
self.setCurrentIndex(index)
else:
self.setCurrentIndex(cursor_index)
def endOfTable(self):
section = self.currentIndex().column()
current_row = self.currentIndex().row()
nr_rows = self.tablemodel.rowCount()
cursor_index = self.moveCursor(QAbstractItemView.MoveRight, Qt.NoModifier)
cursor_section = cursor_index.column()
if (current_row == nr_rows -1) and (section == cursor_section):
return True
return False
class MyTableModel(PyQt4.QtCore.QAbstractTableModel):
NR_COLS = 4
FISHNR, GENDER, WEIGHT, LENGTH = range(NR_COLS)
def __init__(self, datain, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain
self.editable = {}
self.editable[MyTableModel.FISHNR] = True
self.editable[MyTableModel.GENDER] = True
self.editable[MyTableModel.WEIGHT] = False
self.editable[MyTableModel.LENGTH] = True
def rowCount(self, parent=None):
return len(self.arraydata)
#return 2
def columnCount(self, parent=None):
#return len(self.arraydata[0])
return 4
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
def headerData(self, section, orientation, role=PyQt4.QtCore.Qt.DisplayRole):
#self.log.debug("headerdata called, section:%d" % section)
if role == PyQt4.QtCore.Qt.TextAlignmentRole:
if orientation == PyQt4.QtCore.Qt.Horizontal:
return PyQt4.QtCore.QVariant(int(PyQt4.QtCore.Qt.AlignLeft|PyQt4.QtCore.Qt.AlignVCenter))
return PyQt4.QtCore.QVariant(int(PyQt4.QtCore.Qt.AlignRight|PyQt4.QtCore.Qt.AlignVCenter))
if role != PyQt4.QtCore.Qt.DisplayRole:
return PyQt4.QtCore.QVariant()
if orientation == PyQt4.QtCore.Qt.Horizontal:
if section == MyTableModel.FISHNR:
return PyQt4.QtCore.QVariant("Fishnr")
if section == MyTableModel.GENDER:
return PyQt4.QtCore.QVariant("Gender")
if section == MyTableModel.WEIGHT:
return PyQt4.QtCore.QVariant("Weight")
if section == MyTableModel.LENGTH:
return PyQt4.QtCore.QVariant("Length")
return PyQt4.QtCore.QVariant(int(section + 1))
def flags(self, index):
if not index.isValid():
return QtCore.Qt.ItemIsEnabled
section = index.column()
if self.editable[section]:
return QtCore.Qt.ItemFlags(QtCore.QAbstractTableModel.flags(self, index)|QtCore.Qt.ItemIsEditable|QtCore.Qt.ItemIsEnabled)
else:
return QtCore.Qt.NoItemFlags
def get_editable(self):
return self.editable
class MyDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent=None):
super(MyDelegate, self).__init__(parent)
self.parent = parent
def createEditor(self, parent, option, index):
if index.column() == MyTableModel.FISHNR:
editor = QtGui.QLineEdit(parent)
editor.setValidator(QtGui.QIntValidator(1, 9999, parent))
#self.connect(editor, SIGNAL("returnPressed()"),
# self.commitAndCloseEditor)
return editor
elif index.column() == MyTableModel.WEIGHT:
editor = QtGui.QLineEdit(parent)
#self.connect(editor, SIGNAL("returnPressed()"),
# self.commitAndCloseEditor)
return editor
elif index.column() == MyTableModel.LENGTH:
editor = QtGui.QLineEdit(parent)
editor.setValidator(QtGui.QIntValidator(0.000001,99.999999, parent))
#self.connect(editor, SIGNAL("returnPressed()"),
# self.commitAndCloseEditor)
return editor
elif index.column() == MyTableModel.GENDER:
editor = QtGui.QLineEdit(parent)
#self.connect(editor, SIGNAL("returnPressed()"),
# self.commitAndCloseEditor)
return editor
else:
return QtGui.QStyledItemDelegate.createEditor(self,parent, option, index)
def setEditorData(self, editor, index):
if index.isValid():
text = index.model().data(index, QtCore.Qt.DisplayRole).toString()
editor.setText(text)
def setModelData(self, editor, model, index):
#pass
model.setData(index, editor.text())
if __name__ == "__main__":
main()
Peter HJ van der Kamp
Software developer
Wageningen IMARES, afd. Visserij
Postbus 68
1970 AB IJmuiden
Tel. 0317-487176
More information about the PyQt
mailing list