Как создать события нажатия или щелчка мыши в QML / Pyside2 без фактического нажатия мыши - PullRequest
0 голосов
/ 06 августа 2020

Для проекта, который я делаю, мне нужно иметь возможность создавать «искусственные» события мыши, которые может видеть только QML без физического нажатия на мышь.

В моей текущей реализации я пытаюсь используйте события «нажатие клавиши» для запуска этих искусственных событий мыши. В настоящее время я использую функцию «Qt.createQmlObject» для создания MouseEvent, а затем передаю его в качестве параметра для сигнала щелчка мыши. Однако я все время получаю сообщение об ошибке: «MouseEvent не является типом». Я открыт для различных реализаций.

import QtQuick.Controls 2.12
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.11
import QtGraphicalEffects 1.12
import QtMultimedia 5.12
import QtQml.Models 2.12
import "../components"

Item{
   id: widget
   width: 600
   height: 600

   //MouseArea
   MouseArea{
       id: mouseArea
       anchors.fill: parent
       propagateComposedEvents: true
       hoverEnabled: true
       
       onClicked: {
           console.log("The mouse was clicked")
           widget.focus = true 
           mouse.accepted = false
       }

       onPressed: {
           console.log("The mouse was pressed")
           mouse.accept = false
       }

       onEntered:{
           widget.focus = true               
       }
   }

   //Defines key event changes
   Keys.onPressed: {
       if(event.key == Qt.Key_0){
           var mouEvent = Qt.createQmlObject('import QtQuick 2.12; import QtQuick.Controls 2.12; MouseEvent{x: 0; y: 0; accepted: false; button: Qt.LeftButton; buttons: Qt.LeftButton; flags: 0; modifiers: Qt.NoModifier; source: Qt.MouseEventSynthesizedByApplication; wasHeld: false}', mouseArea, "error")
           mouseArea.clicked(mouEvent)
       }
   }
}

1 Ответ

1 голос
/ 07 августа 2020

MouseEvent не является элементом, который может или должен быть создан, проще говоря MouseEvent - это оболочка над QMouseEvent, которая позволяет получать информацию о событии.

При этом вызов сигнала не означает, что событие будет передано, вместо этого вам нужно использовать систему событий Qt, которую нельзя использовать из QML, но из C ++ (в вашем случае это эквивалентно python).

Таким образом, logi c должен создать класс, который уведомляет событие в Qt, а Qt должен отправить событие элементу через окно, как показано ниже:

from PySide2.QtCore import (
    QCoreApplication,
    QEvent,
    QObject,
    QPointF,
    Qt,
    QTimer,
    QUrl,
    Slot,
)
from PySide2.QtGui import QGuiApplication, QMouseEvent
from PySide2.QtQuick import QQuickItem, QQuickView


class MouseEmulator(QObject):
    @Slot(QQuickItem, Qt.MouseButton)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier, QPointF)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier, QPointF, int)
    def mouseClick(self, item, button, modifier=Qt.NoModifier, pos=QPointF(), delay=-1):
        self.mousePress(item, button, modifier, pos, delay)
        self.mouseRelease(item, button, modifier, pos, 2 * delay)

    @Slot(QQuickItem, Qt.MouseButton)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier, QPointF)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier, QPointF, int)
    def mousePress(self, item, button, modifier=Qt.NoModifier, pos=QPointF(), delay=-1):
        self._send_mouse_events(
            QEvent.MouseButtonPress, item, button, modifier, pos, delay
        )

    @Slot(QQuickItem, Qt.MouseButton)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier, QPointF)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier, QPointF, int)
    def mouseRelease(
        self, item, button, modifier=Qt.NoModifier, pos=QPointF(), delay=-1
    ):
        self._send_mouse_events(
            QEvent.MouseButtonRelease, item, button, modifier, pos, delay
        )

    @Slot(QQuickItem, Qt.MouseButton)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier, QPointF)
    @Slot(QQuickItem, Qt.MouseButton, Qt.KeyboardModifier, QPointF, int)
    def mouseDClick(
        self, item, button, modifier=Qt.NoModifier, pos=QPointF(), delay=-1
    ):
        self.mousePress(item, button, modifier, pos, delay)
        self.mouseRelease(item, button, modifier, pos, 2 * delay)
        self.mousePress(item, button, modifier, pos, 3 * delay)
        self._send_mouse_events(
            QEvent.MouseButtonDblClick, item, button, pos, 4 * delay
        )
        self.mouseRelease(item, button, modifier, pos, 5 * delay)

    def _send_mouse_events(self, type_, item, button, modifier, pos, delay):
        window = item.window()
        if pos.isNull():
            pos = item.boundingRect().center()
        sp = item.mapToScene(pos).toPoint()
        event = QMouseEvent(
            type_, pos, window.mapToGlobal(sp), button, button, modifier
        )
        if delay < 0:
            delay = 0

        def on_timeout():
            QCoreApplication.instance().notify(window, event)

        QTimer.singleShot(delay, on_timeout)


def main():
    import os
    import sys

    CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))

    app = QGuiApplication(sys.argv)
    mouse_emulator = MouseEmulator()
    view = QQuickView()
    view.rootContext().setContextProperty("mouse_emulator", mouse_emulator)
    filename = os.path.join(CURRENT_DIR, "main.qml")
    view.setSource(QUrl.fromLocalFile(filename))
    view.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
import QtQuick 2.12

Item{
   id: widget
   width: 600
   height: 600

   MouseArea{
       id: mouseArea
       anchors.fill: parent
       propagateComposedEvents: true
       hoverEnabled: true
       
       onClicked: {
           console.log("The mouse was clicked")
           widget.focus = true 
           mouse.accepted = false
       }

       onPressed: {
           console.log("The mouse was pressed")
           mouse.accept = false
       }

       onEntered:{
           widget.focus = true               
       }
   }

   Keys.onPressed: {
        if(event.key == Qt.Key_0){
            mouse_emulator.mouseClick(widget, Qt.LeftButton)
        }
   }
}
...