QML MouseArea:以编程方式将鼠标移动到 MouseArea 后不会触发 onExited
QML MouseArea: onExited doesn't trigger after programmatically moving mouse into MouseArea
此问题发生在 Windows,但未发生在 Linux。我没有尝试过任何其他平台。
我有一个使用 QCursor
设置鼠标位置的自定义 class(下面的代码)。
以下代码 (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.');
}
}
}
重现问题的步骤:
- 将鼠标放在 window 上。光标将移动到屏幕的左上角,
onExited
将触发。
- 释放鼠标按钮。光标会跳到window.
中间
- 将鼠标移出window。
onExited
应该在用户将鼠标移出 window 时第二次触发,但它没有。有什么办法可以吗
- 让它开火,或者
- 否则检测到鼠标已经移出鼠标区域?
onPositionChanged
仍然触发,但我只能用它来检测鼠标何时接近 MouseArea
的边缘,而不是何时离开。
我尝试在顶部覆盖全局 MouseArea
并传递所有事件,以此作为进行一些手动特殊情况位置检查的方式,但我无法传递悬停事件。
设置鼠标位置的class:
#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);
}
我在主函数中将此 class 注册为 QML 类型:
int main(int argc, char *argv[]) {
// ...
qmlRegisterType<MouseHelper>("io.github.myProject.utilities.mousehelper",
1, 0, "MouseHelper");
}
然后我可以将它导入 QML 并使用它。
作为您问题的解决方法,您可以使用计时器来重置鼠标光标的位置。
在 QML 中:
MouseArea {
...
Timer {
id: timer
interval: 10
repeat: false
onTriggered: {
mouseHelper.setCursorPosition(mouseArea.p.x, mouseArea.p.y)
}
}
onReleased: {
timer.start()
}
...
}
或者在你的 MouseHelper 中 class:
#include <QTimer>
...
void MouseHelper::setCursorPosition(int x, int y) {
QTimer::singleShot(10, this, [x, y]() { QCursor::setPos(x, y); });
}
如果计时器的间隔不是太小,这对我有用。
此问题发生在 Windows,但未发生在 Linux。我没有尝试过任何其他平台。
我有一个使用 QCursor
设置鼠标位置的自定义 class(下面的代码)。
以下代码 (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.');
}
}
}
重现问题的步骤:
- 将鼠标放在 window 上。光标将移动到屏幕的左上角,
onExited
将触发。 - 释放鼠标按钮。光标会跳到window. 中间
- 将鼠标移出window。
onExited
应该在用户将鼠标移出 window 时第二次触发,但它没有。有什么办法可以吗
- 让它开火,或者
- 否则检测到鼠标已经移出鼠标区域?
onPositionChanged
仍然触发,但我只能用它来检测鼠标何时接近 MouseArea
的边缘,而不是何时离开。
我尝试在顶部覆盖全局 MouseArea
并传递所有事件,以此作为进行一些手动特殊情况位置检查的方式,但我无法传递悬停事件。
设置鼠标位置的class:
#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);
}
我在主函数中将此 class 注册为 QML 类型:
int main(int argc, char *argv[]) {
// ...
qmlRegisterType<MouseHelper>("io.github.myProject.utilities.mousehelper",
1, 0, "MouseHelper");
}
然后我可以将它导入 QML 并使用它。
作为您问题的解决方法,您可以使用计时器来重置鼠标光标的位置。
在 QML 中:
MouseArea {
...
Timer {
id: timer
interval: 10
repeat: false
onTriggered: {
mouseHelper.setCursorPosition(mouseArea.p.x, mouseArea.p.y)
}
}
onReleased: {
timer.start()
}
...
}
或者在你的 MouseHelper 中 class:
#include <QTimer>
...
void MouseHelper::setCursorPosition(int x, int y) {
QTimer::singleShot(10, this, [x, y]() { QCursor::setPos(x, y); });
}
如果计时器的间隔不是太小,这对我有用。