Reputation: 5629
I'm trying to implement "things" on a QTableView. So, I started to override its keyPressEvent method, as it's described everywhere:
if e.key() == QtCore.Qt.Key_F2 and self.tableau.hasFocus():
blabla
elif e.key() == QtCore.Qt.Key_Return and self.tableau.hasFocus():
blabla
#TEST
elif e.key() == QtCore.Qt.Key_Right:
print("right")
elif e.key() == QtCore.Qt.Key_Down:
print("down")
else:
print("waza")
I can handle the F2 and the Return events, they work. But not the Key_Down event ! The Key_right works as well, but not the Down. I think it's because QTableWidget "intercepts" some of the events. When normal letters are pressed, no event is "emitted" either, for example.
I would like to access all the events (or at least the Up and Down events), how can I do that ?
EDIT:
The view I use is basically a QTableView, which I modified a bit:
class ViewPerso(QtGui.QTableView):
def __init__(self, parent=None):
super(ViewPerso, self).__init__(parent)
self.parent = parent
def currentChanged(self, current, previous):
index = current.sibling(current.row(), 4)
try:
if not index.data() or len(self.parent.vidsSelected()) > 1:
return
except AttributeError:
pass
self.clicked.emit(current)
self.scrollTo(current)
def keyboardSearch(self, search):
pass
I do not use QTableWidget, it doesn't do what I want. I also subclassed the view delegate, but normally (normally), nothing should interfere.
Here is how I use my view: I load a model, a proxy, and then I use my view:
self.modele = ModelPerso()
self.modele.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
self.modele.setTable("videos")
self.modele.select()
self.proxy = QtGui.QSortFilterProxyModel()
self.proxy.setSourceModel(self.modele)
self.tableau = ViewPerso(self)
self.tableau.setModel(self.proxy)
self.tableau.setItemDelegate(ViewDelegate(self))
I don't know where the keypresses end up, for now, they just disappear. I think (I think), each widget has a way to treat keypresses event, and maybe QTableView ignores the keys up and down ?
Upvotes: 2
Views: 2986
Reputation: 15642
There seems to be a bit of confusion in the question and in the answers. If you want to propagate key events (for example) from your QTableView
up to its parent/ancestor widget(s), this should usually work:
def keyPressEvent(self, event):
print(f'kpe TableView {event}')
# super().keyPressEvent(event)
self.parent().keyPressEvent(event)
... if you comment out the super()
line there should be no need to do event.ignore()
... although certain components other than QTableView
may handle things differently, particularly editors, I suspect.
Anyway, the next thing is to understand what the parent is and what happens to a KeyPressEvent
in it. In my case the parent was a QFrame
, positioned in a hierarchy of QWidget
s/QLayout
s. However I also have an event filter set up on the QMainWindow
, i.e. right at the top of the hierarchy, like this:
class KeyPressEater(QtCore.QObject):
def __init__(self, main_window):
super().__init__()
self.main_window = main_window
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.KeyPress:
if event.modifiers() == QtCore.Qt.NoModifier:
if event.key() == QtCore.Qt.Key_Return:
self.main_window.entry_box.keyPressEvent(event)
return super().eventFilter(obj, event)
In the QMainWindow
constructor:
self.kpe = KeyPressEater(self)
self.installEventFilter(self.kpe)
And I confirm that the event in question (on pressing Return with focus on the QTableView
) gets propagated, without any further explicit wiring, all the way up to the KeyPressEater
installed on the QMainWindow
, and is thus caught by it and fires the key press event on the entry_box
as configured by this line:
self.main_window.entry_box.keyPressEvent(event)
Of course, you may not want all key press events to be propagated up from the table view: filtering should be easy enough.
Upvotes: 0
Reputation: 3450
For implemented outside class, You have to override this keyPressEvent method out side. Like this example:
import sys
from PyQt4 import QtCore, QtGui
class ViewPerso (QtGui.QTableView):
def __init__(self, parent = None):
super(ViewPerso, self).__init__(parent)
self.parent = parent
def currentChanged (self, current, previous):
index = current.sibling(current.row(), 4)
try:
if not index.data() or len(self.parent.vidsSelected()) > 1:
return
except AttributeError:
pass
self.clicked.emit(current)
self.scrollTo(current)
def keyboardSearch (self, search):
pass
class exampleQMainWindow (QtGui.QMainWindow):
def __init__ (self):
super(exampleQMainWindow, self).__init__()
testQTableWidget = ViewPerso(self)
self.setCentralWidget(testQTableWidget)
testQTableWidget.keyPressEvent = self.keyPressEvent
def keyPressEvent (self, eventQKeyEvent):
key = eventQKeyEvent.key()
if key == QtCore.Qt.Key_F1:
print 'Help'
elif key == QtCore.Qt.Key_F5:
print 'Reload'
elif key == QtCore.Qt.Key_Left:
print 'Left'
elif key == QtCore.Qt.Key_Up:
print 'Up'
elif key == QtCore.Qt.Key_Right:
print 'Right'
elif key == QtCore.Qt.Key_Down:
print 'Down'
app = QtGui.QApplication([])
window = exampleQMainWindow()
window.show()
sys.exit(app.exec_())
Upvotes: 0
Reputation: 5629
Ok, I finally ended up doing this:
class ViewPerso (QtGui.QTableView):
def __init__(self, parent = None):
super(ViewPerso, self).__init__(parent)
self.parent = parent
def currentChanged (self, current, previous):
index = current.sibling(current.row(), 4)
try:
if not index.data() or len(self.parent.vidsSelected()) > 1:
return
except AttributeError:
pass
self.clicked.emit(current)
self.scrollTo(current)
def keyboardSearch (self, search):
pass
def keyPressEvent (self, e):
super(ViewPerso, self).keyPressEvent(e)
e.ignore()
The event was probably stuck in ViewPerso, so by overriding its keyPressEvent method like this, I get the usual treatments QTableWidget does on the events, and I the event is propagated to the parent widget, so I can use it again.
I tried to do what you showed in your edit, but it simply does not work for me, I don't really know why. My program is also very big (~10k lines), so the reason could come from anywhere. But thanks to make me realize where the error came from.
Upvotes: 1