How to forward Qt Mouse event to QQuickView?

2019-08-21 01:45发布

问题:

In my QMainWindow, I have a QFrame and a QWidget that wraps a QQuickView and displays the ui through a qml 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 within QQuickView.

The hover event within QQuickView has no issues and I can successfully get the hover event. The problem arises when on mouse-down within QFrame followed by a mouse-move into QQuickView, I am unable to get any mouse events in QQuickView.

On the left is the QFrame and the right is the QQuickView.

Hovering in QQuickView independently:

Mouse-down in QFrame and mouse-move into QQuickView:

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 the QFrame to the QQuickView or there seems to be some form of global mouse events to be handled.

How can I go about achieving this?

回答1:

turns out i was using the wrong qml element. DropArea should have been used in the qml.

import QtQuick 2.7

Rectangle {

    id: root

    anchors.fill: parent
    color: 'transparent'

    Column {
        anchors.centerIn: parent
        Rectangle {
            width: 50
            height: 50
            color: 'red'
            anchors.horizontalCenter: parent.horizontalCenter
            DropArea {
                anchors.fill: parent
                onEntered: parent.color = 'blue'
                onExited: parent.color = 'red'
                onDropped: console.log('triggger this thing yo')
            }
        }
        Text {
            width: parent.parent.width
            text: 'on hover over box, color changes from red to blue and vice versa when hover out'
            wrapMode: Text.Wrap
            horizontalAlignment: Text.AlignHCenter
        }
    }
}

hope this will be able to help someone out down the road. credits to raven-worx on Qt Forum for the solution.



标签: python qml pyqt5