有两个MouseAreas有两个不同的职责,一个(绿色)部分位于另一个(红色)之上。我想在 red MA悬停时改变光标的形状(即使它在绿色 MA下)并且我希望绿色 MA到对压力做出反应而没有别的。
两个MA可能位于不同的文件中,所以我不想在它们之间建立明确的依赖关系,就像在 red 中的containsMouse更改时在绿色中设置正确的cursorShape一样。有没有办法阻止绿色 MouseArea处理光标形状?
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
visible: true
width: 200
height: 200
Rectangle { anchors.fill: parent; color: "yellow"; }
MouseArea {
width: 150
height: 150
hoverEnabled: true
cursorShape: Qt.OpenHandCursor
Rectangle { anchors.fill: parent; color: "red"; }
onPositionChanged: console.log("position", mouse.x, mouse.y)
onContainsMouseChanged: console.log("containsMouse", containsMouse)
}
MouseArea {
x: 50
y: 50
width: 150
height: 150
hoverEnabled: false
Rectangle { anchors.fill: parent; color: "green"; }
onPressed: console.log("Ahoj!")
}
}
答案 0 :(得分:3)
MouseArea
属性或任何其他现成解决方案无法执行此操作。 MouseArea
始终设置一些游标形状 - 如果未指定cursorShape属性,则使用默认值(Qt.ArrowCursor
)
您当然可以使用mapToItem()
/ mapFromItem()
来解决此问题(正如Mitch建议的那样)。但也有其他可能性:
您可以临时更改覆盖鼠标区域的visible
到false
或者,如果MouseArea
都是兄弟姐妹,则可以对z
属性进行操作,以获得适合您需要的特定对象层次结构。
答案 1 :(得分:2)
我认为这样做是不可能的,至少从QML中可以做到这一点。绿色鼠标区域没有hoverEnabled
设置为true,因此您无法接收任何位置更改。
解决此问题的更好方法是使用更大的MouseArea
填充您感兴趣的最大区域,并使用mapToItem() / mapFromItem()翻译全局鼠标位置到本地坐标以与每个鼠标区域进行比较:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: window
visible: true
width: 200
height: 200
Rectangle {
anchors.fill: parent
color: "yellow"
}
MouseArea {
id: globalMouseArea
anchors.fill: parent
hoverEnabled: true
}
MouseArea {
id: redMouseArea
width: 150
height: 150
cursorShape: containsMouse ? Qt.OpenHandCursor : Qt.ArrowCursor
enabled: false
readonly property bool containsMouse: {
var relativePos = mapFromItem(globalMouseArea, globalMouseArea.mouseX, globalMouseArea.mouseY);
return contains(Qt.point(relativePos.x, relativePos.y));
}
Rectangle {
anchors.fill: parent
color: "red"
}
}
Rectangle {
id: greenMouseArea
x: 50
y: 50
width: 150
height: 150
color: containsMouse ? "brown" : "green"
readonly property bool containsMouse: {
var relativePos = mapFromItem(globalMouseArea, globalMouseArea.mouseX, globalMouseArea.mouseY);
return contains(Qt.point(relativePos.x, relativePos.y));
}
Connections {
target: globalMouseArea
onPressed: if (greenMouseArea.containsMouse) greenMouseArea.pressed()
}
signal pressed
onPressed: console.log("Ahoj!")
}
}
如您所见,绿色鼠标区域不再是鼠标区域。看起来堆叠顺序高于另一个鼠标区域的鼠标区域将阻止较低鼠标区域的位置更改,即使较高的区域没有hoverEnabled
设置为true。
另外,请注意,如果QTBUG-41452没有,则会更简洁一些。也就是说,您可以缩短containsMouse
表达式:
readonly property bool containsMouse: contains(mapFromItem(globalMouseArea, globalMouseArea.mouseX, globalMouseArea.mouseY))
如果您在这里关注代码重复,那么您可以使用函数代替:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: window
visible: true
width: 200
height: 200
Rectangle {
anchors.fill: parent
color: "yellow"
}
MouseArea {
id: globalMouseArea
anchors.fill: parent
hoverEnabled: true
}
function containsMouse(item) {
var relativePos = globalMouseArea.mapToItem(item, globalMouseArea.mouseX, globalMouseArea.mouseY);
return item.contains(Qt.point(relativePos.x, relativePos.y));
}
MouseArea {
id: redMouseArea
width: 150
height: 150
cursorShape: window.containsMouse(redMouseArea) ? Qt.OpenHandCursor : Qt.ArrowCursor
enabled: false
Rectangle {
anchors.fill: parent
color: "red"
}
}
Rectangle {
id: greenMouseArea
x: 50
y: 50
width: 150
height: 150
color: containsMouse ? "brown" : "green"
readonly property bool containsMouse: window.containsMouse(greenMouseArea)
Connections {
target: globalMouseArea
onPressed: if (greenMouseArea.containsMouse) greenMouseArea.pressed()
}
signal pressed
onPressed: console.log("Ahoj!")
}
}
我在绿色鼠标区域使用了一个属性,否则会两次调用containsMouse()
,这很浪费。
答案 2 :(得分:1)
您可以像下面一样创建自己的CusorShapeArea。它将帮助您更轻松地控制光标形状。
首先创建C ++类CursorShapeArea:
cursorshapearea.h
#ifndef CURSORSHAPEAREA_H
#define CURSORSHAPEAREA_H
#include <QDeclarativeItem>
class QsltCursorShapeArea : public QDeclarativeItem
{
Q_OBJECT
Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape NOTIFY cursorShapeChanged)
public:
explicit QsltCursorShapeArea(QDeclarativeItem *parent = 0);
Qt::CursorShape cursorShape() const;
Q_INVOKABLE void setCursorShape(Qt::CursorShape cursorShape);
private:
int m_currentShape;
signals:
void cursorShapeChanged();
};
#endif // CURSORSHAPEAREA_H
cursorshapearea.cpp
#include "cursorshapearea.h"
QsltCursorShapeArea::QsltCursorShapeArea(QDeclarativeItem *parent) :
QDeclarativeItem(parent),
m_currentShape(-1)
{
}
Qt::CursorShape QsltCursorShapeArea::cursorShape() const
{
return cursor().shape();
}
void QsltCursorShapeArea::setCursorShape(Qt::CursorShape cursorShape)
{
if (m_currentShape == (int) cursorShape)
return;
setCursor(cursorShape);
emit cursorShapeChanged();
m_currentShape = cursorShape;
}
然后注册此qml类型:
#include <QtDeclarative>
#include "cursorshapearea.h"
int main(int argc, char **argv)
{
...
qmlRegisterType<CursorShapeArea>("MyTools", 1, 0, "CursorShapeArea");
...
}
然后在QML中使用它,在您的问题中:
import QtQuick 1.1
import CursorShapeArea 0.1
Window {
visible: true
width: 200
height: 200
Rectangle { anchors.fill: parent; color: "yellow"; }
MouseArea {
id: redArea
width: 150
height: 150
hoverEnabled: true
//cursorShape: Qt.OpenHandCursor
Rectangle { anchors.fill: parent; color: "red"; }
onPositionChanged: console.log("position", mouse.x, mouse.y)
onContainsMouseChanged: console.log("containsMouse", containsMouse)
}
MouseArea {
x: 50
y: 50
width: 150
height: 150
hoverEnabled: false
Rectangle { anchors.fill: parent; color: "green"; }
onPressed: console.log("Ahoj!")
}
CursorShapeArea {
anchors.fill: redArea
cursorShape: Qt.OpenHandCursor
}
}
答案 3 :(得分:0)
您可以在绿色鼠标区域将cursorShape
设置为undefined
,以防止其更改光标。