QML MouseArea: onExited non si attiva dopo aver spostato il mouse in modo programmatico in MouseArea
Questo problema si verifica su Windows, ma non su Linux. Non ho provato altre piattaforme.
Ho una classe personalizzata (codice sotto) che utilizza QCursor
per impostare la posizione del mouse.
Il problema è con il seguente codice ( repo ):
import QtQuick 2.15
import QtQuick.Window 2.15
// Custom C++ class, implementation below
import io.github.myProject.utilities.mousehelper 1.0
Window {
visible: true
width: 800
height: 600
MouseHelper { id: mouseHelper }
MouseArea {
id: mouseArea
hoverEnabled: true
anchors.fill: parent
property var p
onPressed: {
p = mouseArea.mapToGlobal(
mouseArea.width * 0.5, mouseArea.height * 0.5);
mouseHelper.setCursorPosition(0, 0);
}
onReleased: {
mouseHelper.setCursorPosition(p.x, p.y);
}
onExited: {
console.log('This should happen twice, but it only happens once.');
}
}
}
Passaggi per riprodurre il problema:
- Mouse in basso sulla finestra. Il cursore si sposterà in alto a sinistra dello schermo e
onExited
si attiverà. - Rilascia il pulsante del mouse. Il cursore salterà al centro della finestra.
- Sposta il mouse fuori dalla finestra.
onExited
dovrebbe attivarsi una seconda volta quando l'utente sposta il mouse fuori dalla finestra, ma non lo fa. C'è un modo in cui posso farlo anch'io
- farlo sparare, o
- altrimenti rileva che il mouse è uscito dall'area del mouse?
onPositionChanged
si attiva ancora, ma posso usarlo solo per rilevare quando il mouse è vicino al bordo del MouseArea
, non quando è uscito.
Ho provato a sovrapporre un globale MouseArea
in cima e a passare tutti gli eventi come un modo per eseguire un controllo manuale della posizione dei casi speciali, ma non sono riuscito a passare gli eventi al passaggio del mouse.
La classe per impostare la posizione del mouse:
#ifndef MOUSEHELPER_H
#define MOUSEHELPER_H
#include <QObject>
#include <QCursor>
class MouseHelper : public QObject {
Q_OBJECT
public:
explicit MouseHelper(QObject *parent = nullptr);
Q_INVOKABLE void setCursorPosition(int x, int y);
signals:
public slots:
};
#endif // MOUSEHELPER_H
#include "mousehelper.h"
#include <QGuiApplication>
MouseHelper::MouseHelper(QObject *parent) : QObject(parent) {}
void MouseHelper::setCursorPosition(int x, int y) {
QCursor::setPos(x, y);
}
Registro questa classe come tipo con QML nella mia funzione principale:
int main(int argc, char *argv[]) {
// ...
qmlRegisterType<MouseHelper>("io.github.myProject.utilities.mousehelper",
1, 0, "MouseHelper");
}
Posso quindi importarlo in QML e usarlo.
Risposte
Per ovviare al tuo problema puoi utilizzare un timer per reimpostare la posizione del cursore del mouse.
O in QML:
MouseArea {
...
Timer {
id: timer
interval: 10
repeat: false
onTriggered: {
mouseHelper.setCursorPosition(mouseArea.p.x, mouseArea.p.y)
}
}
onReleased: {
timer.start()
}
...
}
O nella tua classe MouseHelper:
#include <QTimer>
...
void MouseHelper::setCursorPosition(int x, int y) {
QTimer::singleShot(10, this, [x, y]() { QCursor::setPos(x, y); });
}
Questo funziona per me se l'intervallo del timer non è troppo piccolo.