How to forward Qt Mouse event to QQuickView?
-
In my
QMainWindow
, I have aQFrame
and aQWidget
that wraps aQQuickView
and displays the ui through aqml
file.I am trying to implement a drag and drop functionality where, on mouse-down and mouse-move in the
QFrame
, a thumbnail follows the cursor's position throughout until mouse-release. The mouse-release will happen withinQQuickView
.The hover event within
QQuickView
has no issues and I can successfully get the hover event. The problem arises when on mouse-down withinQFrame
followed by a mouse-move intoQQuickView
, I am unable to get any mouse events inQQuickView
.On the left is the
QFrame
and the right is theQQuickView
.Hovering in
QQuickView
independently:Mouse-down in
QFrame
and mouse-move intoQQuickView
:Any mouse events can only be captured after mouse-release.
These are what I have written so far:
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QFrame, QLabel, QGridLayout, QVBoxLayout from PyQt5.QtCore import Qt, QMimeData, QUrl from PyQt5.QtGui import QDrag, QPixmap from PyQt5.QtQuick import QQuickView class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.centralWidget = QWidget(self) gridlayout = QGridLayout(self.centralWidget) gridlayout.setContentsMargins(0,0,0,0) gridlayout.setHorizontalSpacing(0) gridlayout.setVerticalSpacing(0) self.setCentralWidget(self.centralWidget) self.leftPanel = QVBoxLayout() self.rightPanel = QVBoxLayout() gridlayout.addLayout(self.leftPanel, 0, 0, 1, 1) gridlayout.addLayout(self.rightPanel, 0, 1, 1, 1) gridlayout.setSpacing(0) self.setStyleSheet("background:grey") self.resize(300, 200) self.show() class Left(QFrame): def __init__(self): super().__init__() self.resize(500, 500) self.label = QLabel(self) self.label.resize(50, 50) def mouseMoveEvent(self, e): mimeData = QMimeData() drag = QDrag(self) self.thumbnail = QPixmap('./test.png').scaled(50, 50, Qt.KeepAspectRatio) drag.setPixmap(self.thumbnail) drag.setMimeData(mimeData) drag.exec_(Qt.MoveAction) class Right(QQuickView): def __init__(self, parent=None): super().__init__(parent) self.rootContext().setContextProperty('Right', self) self.setSource(QUrl('./drag.qml')) self.setMinimumHeight(200) self.setMinimumWidth(150) if __name__ == '__main__': app = QApplication(sys.argv) main_window = MainWindow() main_window.leftPanel.addWidget(Left()) main_window.rightPanel.addWidget(QWidget.createWindowContainer(Right())) app.exec_()
Based on what I have read from different sources and the
Qt
documentation, I suppose I have to forward the events from theQFrame
to theQQuickView
or there seems to be some form of global mouse events to be handled.How can I go about achieving this?
-
In my
QMainWindow
, I have aQFrame
and aQWidget
that wraps aQQuickView
and displays the ui through aqml
file.I am trying to implement a drag and drop functionality where, on mouse-down and mouse-move in the
QFrame
, a thumbnail follows the cursor's position throughout until mouse-release. The mouse-release will happen withinQQuickView
.The hover event within
QQuickView
has no issues and I can successfully get the hover event. The problem arises when on mouse-down withinQFrame
followed by a mouse-move intoQQuickView
, I am unable to get any mouse events inQQuickView
.On the left is the
QFrame
and the right is theQQuickView
.Hovering in
QQuickView
independently:Mouse-down in
QFrame
and mouse-move intoQQuickView
:Any mouse events can only be captured after mouse-release.
These are what I have written so far:
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QFrame, QLabel, QGridLayout, QVBoxLayout from PyQt5.QtCore import Qt, QMimeData, QUrl from PyQt5.QtGui import QDrag, QPixmap from PyQt5.QtQuick import QQuickView class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.centralWidget = QWidget(self) gridlayout = QGridLayout(self.centralWidget) gridlayout.setContentsMargins(0,0,0,0) gridlayout.setHorizontalSpacing(0) gridlayout.setVerticalSpacing(0) self.setCentralWidget(self.centralWidget) self.leftPanel = QVBoxLayout() self.rightPanel = QVBoxLayout() gridlayout.addLayout(self.leftPanel, 0, 0, 1, 1) gridlayout.addLayout(self.rightPanel, 0, 1, 1, 1) gridlayout.setSpacing(0) self.setStyleSheet("background:grey") self.resize(300, 200) self.show() class Left(QFrame): def __init__(self): super().__init__() self.resize(500, 500) self.label = QLabel(self) self.label.resize(50, 50) def mouseMoveEvent(self, e): mimeData = QMimeData() drag = QDrag(self) self.thumbnail = QPixmap('./test.png').scaled(50, 50, Qt.KeepAspectRatio) drag.setPixmap(self.thumbnail) drag.setMimeData(mimeData) drag.exec_(Qt.MoveAction) class Right(QQuickView): def __init__(self, parent=None): super().__init__(parent) self.rootContext().setContextProperty('Right', self) self.setSource(QUrl('./drag.qml')) self.setMinimumHeight(200) self.setMinimumWidth(150) if __name__ == '__main__': app = QApplication(sys.argv) main_window = MainWindow() main_window.leftPanel.addWidget(Left()) main_window.rightPanel.addWidget(QWidget.createWindowContainer(Right())) app.exec_()
Based on what I have read from different sources and the
Qt
documentation, I suppose I have to forward the events from theQFrame
to theQQuickView
or there seems to be some form of global mouse events to be handled.How can I go about achieving this?
@eugeneoei said in How to forward Qt Mouse event to QQuickView?:
Based on what I have read from different sources and the Qt documentation, I suppose I have to forward the events from the QFrame to the QQuickView or there seems to be some form of global mouse events to be handled.
no, no event forwarding needed here. You are just listening to wrong events in QML.
Since you start a drag, you should also listen to drag events in QML. See DropArea element and it's containsDrag property. -
@eugeneoei said in How to forward Qt Mouse event to QQuickView?:
Based on what I have read from different sources and the Qt documentation, I suppose I have to forward the events from the QFrame to the QQuickView or there seems to be some form of global mouse events to be handled.
no, no event forwarding needed here. You are just listening to wrong events in QML.
Since you start a drag, you should also listen to drag events in QML. See DropArea element and it's containsDrag property.@raven-worx you sir saved my life! I cant believe i was stuck at this for 2 days, when it was simply just about using the right object in qml. thanks!