Application stops receiving Keypress events during drag operation
-
I'm working on a project where I want to drag shaped widgets onto a grid, and I want to be able to rotate the shape when the
R key
is pressed. However, despite my best efforts, all keyboard events stop being processed when a drag operation is in progress.I've tried:
- a custom QDrag class with an event filter installed.
- having a
keyPressEvent
function on my window class, my widget classes, and the QDrag class - Installing event filters on the QApplication and the window
StrongFocus
policy withsetFocus
on the widgetgrabKeyboard
on the window and widget
I've tried both PyQt5 and PyQt6 to no avail. For what it's worth, I'm on Linux. I haven't tested on Windows. No matter what I've tried though, the application stops receiving keyboard events during a drag operation.
I haven't been able to find any information or examples online about getting keyboard input during a drag operation, so I've finally relented and am asking here about this issue.
Below is a minimal(-ish) viable reproduction that also includes what I have going on:
import sys from PyQt6.QtWidgets import ( QApplication, QMainWindow, QWidget, QHBoxLayout, QLabel, QFrame ) from PyQt6.QtGui import QPixmap, QDrag from PyQt6.QtCore import Qt, QMimeData class DragTestWindow(QMainWindow): def __init__(self): super().__init__() self.setFixedSize(800, 600) main_widget = QWidget() self.setCentralWidget(main_widget) main_layout = QHBoxLayout() main_widget.setLayout(main_layout) block = DraggableBlock() main_layout.addWidget(block) def keyPressEvent(self, key): print("DragTestWindow keyPressEvent") class DraggableBlock(QLabel): def __init__(self, parent=None): super().__init__(parent) self.setFrameShape(QFrame.Shape.Box) self.setFixedSize(100, 50) self.setStyleSheet("background-color: gray;") self.setText("Block") self.setAlignment(Qt.AlignmentFlag.AlignCenter) def mousePressEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: drag = DragWithRotation(self) mime_data = QMimeData() drag.setMimeData(mime_data) drag.setHotSpot(event.pos()) pixmap = QPixmap(self.size()) self.render(pixmap) drag.setPixmap(pixmap) drag.exec(Qt.DropAction.MoveAction) def keyPressEvent(self, ev): print("DraggableBlock keyPressEvent") class DragWithRotation(QDrag): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def keyPressEvent(self, event): print("DragWithRotation keyPressEvent") def exec_(self, *args, **kwargs): application = QApplication.instance() application.installEventFilter(self) super().exec(*args, **kwargs) application.removeEventFilter(self) def eventFilter(self, obj, event): if event.type() == event.KeyPress: self.keyPressEvent(event) return True return False def main(): app = QApplication(sys.argv) dragtest_window = DragTestWindow() dragtest_window.show() sys.exit(app.exec()) if __name__ == "__main__": main()
-
I've found a solution using
QAbstractNativeEventFilter
to grab the keyboard events that never make it to the standard Qt event system. -