ContainsMouse 在父更改时给出了错误的值
ContainsMouse gives incorrect value on parent change
在 QML 中,当 mouse is currently inside the mouse area. Unfortunately, this is not always the case. In the following code, the red square turns blue when the MouseArea within it contains the mouse (ContainsMouse is true). However, if you hit the control key while the square is blue, when the square is reparented to the Window's contentItem, the containsMouse property is not updated (as indicated by the text in the middle of the square). The square will still be blue even though it doesn't contain the mouse anymore. Is there anyway to tell the MouseArea to refresh it's containsMouse property?
时,MouseArea 的 containsMouse 属性 应该 return 为真
代码如下:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 800
height: 500
visible: true
Rectangle {
id: square
width: 200
height: 200
focus: true
color: my_mouse_area.containsMouse ? "blue" : "red"
MouseArea {
id: my_mouse_area
anchors.fill: parent
hoverEnabled: true
onClicked: {
my_mouse_area.x = 200
}
}
Text {
anchors.centerIn: parent
text: my_mouse_area.containsMouse + ""
font.pixelSize: 20
}
Keys.onPressed: {
if(event.key === Qt.Key_Control){
second_window.show()
square.parent = second_window.contentItem
}
}
}
Window {
id: second_window
width: 400
height: 400
visible: false
}
}
我想出的解决方案是使用定时器,但间隔为零,因此闪烁为零。您可以尝试将间隔设置为更高的值,以查看发生了什么。诀窍是使用“visible: !tmr.running”设置依赖于计时器 运行 的矩形可见性,并在矩形的父级更改后立即启动计时器。
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 800
height: 500
visible: true
Rectangle {
id: square
width: 200
height: 200
focus: true
color: my_mouse_area.containsMouse ? "blue" : "red"
visible: !tmr.running
Timer {
id: tmr
interval: 0
}
MouseArea {
id: my_mouse_area
anchors.fill: parent
hoverEnabled: true
onClicked: {
my_mouse_area.x = 200
}
}
Text {
anchors.centerIn: parent
text: my_mouse_area.containsMouse + ""
font.pixelSize: 20
}
Keys.onPressed: {
if(event.key === Qt.Key_Control){
second_window.show()
square.parent = second_window.contentItem
tmr.start()
}
}
}
Window {
id: second_window
width: 400
height: 400
visible: false
}
}
我不喜欢我的第一个解决方案,所以我做了另一个更复杂的解决方案,但这不是一个纯粹的 QML 解决方案。诀窍在于,在更改父级时,您应该调用一个 C++ 方法,在该方法中将鼠标移动事件发送回鼠标区域,这样它将重新评估悬停的 aka containsMouse 布尔值。这是一个更好的解决方案,但仍然是一种解决方法。
确保您有一个简单的 QObject 派生 class,例如 MyObject,使用以下 Q_INVOKABLE 方法:
class MyObject : public QObject
{
Q_OBJECT
//
// constuctor and whatnot
//
Q_INVOKABLE void sendMouseMoveEventTo(QObject* item)
{
QEvent* e = new QEvent(QEvent::MouseMove);
QCoreApplication::sendEvent(item, e);
}
};
在 main.cpp 中创建它的一个实例,并设置为上下文 属性,这样您就可以从 QML 访问它:
MyObject myObject;
engine.rootContext()->setContextProperty("myObject", &myObject);
最后在 QML 矩形中添加:
onParentChanged: {
myObject.sendMouseMoveEventTo(my_mouse_area)
}
在 QML 中,当 mouse is currently inside the mouse area. Unfortunately, this is not always the case. In the following code, the red square turns blue when the MouseArea within it contains the mouse (ContainsMouse is true). However, if you hit the control key while the square is blue, when the square is reparented to the Window's contentItem, the containsMouse property is not updated (as indicated by the text in the middle of the square). The square will still be blue even though it doesn't contain the mouse anymore. Is there anyway to tell the MouseArea to refresh it's containsMouse property?
代码如下:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 800
height: 500
visible: true
Rectangle {
id: square
width: 200
height: 200
focus: true
color: my_mouse_area.containsMouse ? "blue" : "red"
MouseArea {
id: my_mouse_area
anchors.fill: parent
hoverEnabled: true
onClicked: {
my_mouse_area.x = 200
}
}
Text {
anchors.centerIn: parent
text: my_mouse_area.containsMouse + ""
font.pixelSize: 20
}
Keys.onPressed: {
if(event.key === Qt.Key_Control){
second_window.show()
square.parent = second_window.contentItem
}
}
}
Window {
id: second_window
width: 400
height: 400
visible: false
}
}
我想出的解决方案是使用定时器,但间隔为零,因此闪烁为零。您可以尝试将间隔设置为更高的值,以查看发生了什么。诀窍是使用“visible: !tmr.running”设置依赖于计时器 运行 的矩形可见性,并在矩形的父级更改后立即启动计时器。
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 800
height: 500
visible: true
Rectangle {
id: square
width: 200
height: 200
focus: true
color: my_mouse_area.containsMouse ? "blue" : "red"
visible: !tmr.running
Timer {
id: tmr
interval: 0
}
MouseArea {
id: my_mouse_area
anchors.fill: parent
hoverEnabled: true
onClicked: {
my_mouse_area.x = 200
}
}
Text {
anchors.centerIn: parent
text: my_mouse_area.containsMouse + ""
font.pixelSize: 20
}
Keys.onPressed: {
if(event.key === Qt.Key_Control){
second_window.show()
square.parent = second_window.contentItem
tmr.start()
}
}
}
Window {
id: second_window
width: 400
height: 400
visible: false
}
}
我不喜欢我的第一个解决方案,所以我做了另一个更复杂的解决方案,但这不是一个纯粹的 QML 解决方案。诀窍在于,在更改父级时,您应该调用一个 C++ 方法,在该方法中将鼠标移动事件发送回鼠标区域,这样它将重新评估悬停的 aka containsMouse 布尔值。这是一个更好的解决方案,但仍然是一种解决方法。
确保您有一个简单的 QObject 派生 class,例如 MyObject,使用以下 Q_INVOKABLE 方法:
class MyObject : public QObject
{
Q_OBJECT
//
// constuctor and whatnot
//
Q_INVOKABLE void sendMouseMoveEventTo(QObject* item)
{
QEvent* e = new QEvent(QEvent::MouseMove);
QCoreApplication::sendEvent(item, e);
}
};
在 main.cpp 中创建它的一个实例,并设置为上下文 属性,这样您就可以从 QML 访问它:
MyObject myObject;
engine.rootContext()->setContextProperty("myObject", &myObject);
最后在 QML 矩形中添加:
onParentChanged: {
myObject.sendMouseMoveEventTo(my_mouse_area)
}