Как включить дочерние мыши наведите курсор в родительском MouseArea с помощью QML?
Я хочу реализовать следующий сценарий в QML.
![Scenario]()
Вот пример/упрощенный делегат для элемента ListView
:
Component {
Item {
id: container
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: {
container.ListView.view.currentIndex = index
container.forceActiveFocus();
}
onEntered: {
actionList.state = "SHOW";
myItem.state = "HOVER"
}
onExited: {
actionList.state = "HIDE";
myItem.state = "NORMAL"
}
Rectangle {
id: myItem
color: "gray"
anchors.fill: parent
Row {
id: actionList
spacing: 5; anchors.fill: parent
Image {
id: helpAction
source: "" //Some image address
width: 16; height: 16; fillMode: Image.PreserveAspectFit
states: [
State {
name: "NORMAL"
PropertyChanges { target: helpAction; opacity: 0.7 }
},
State {
name: "HOVER"
PropertyChanges { target: helpAction; opacity: 1.0 }
}
]
MouseArea {
hoverEnabled: true
anchors.fill: parent
onEntered: {
parent.state = "HOVER";
}
onExited: {
parent.state = "NORMAL";
}
}
states: [
State {
name: "SHOW"
PropertyChanges { target: actionList; visible: false }
},
State {
name: "HIDE"
PropertyChanges { target: actionList; visible: true }
}
]
}
//Other action buttons...
states: [
// `NORMAL` and `HOVER` states definition here...
]
}
}
}
}
Но у меня проблема с MouseArea
.
Внутренний MouseArea
(actionButton) не работает должным образом для события entered
. Когда мышь вводит кнопку действия, внешний MouseArea
запускает событие exited
.
Есть ли ошибка в моем коде? Как правило, как реализовать такой сценарий в QML?
Ответы
Ответ 1
Я столкнулся с этой же проблемой и наткнулся на ответ в документации QtQuick 5.0 для MouseArea
. Ответ на это на самом деле довольно простой.
Если вы хотите включить дочерние мыши наведите курсор в родительский MouseArea
, сделайте дочерний MouseArea
дочерний элемент родительского MouseArea
:
MouseArea {
id: parent
MouseArea {
id: child
}
}
Поскольку у меня есть собственный тип Widget
, который будет использоваться в качестве родительского представления, я получил свойство default
, являющееся дочерними элементами MouseArea
:
Item {
default property alias children: mouseArea.data
MouseArea {
id: mouseArea
}
}
Ответ 2
создавать состояния для каждого состояния элементов в представлении, тогда вы можете использовать такие вещи, как операторы или операторы case для изменения этих свойств. Другими словами, попробуйте не устанавливать свои элементы в работу с MouseArea, а по свойствам. Свойства элементов для работы с заданными свойствами Я надеюсь, что это поможет, если не здесь, например:
EDIT Я добавил, что цвет будет прозрачным. если нет мыши, что бы это ни было. Если бы я использовал изображение, я использовал бы прозрачность, а затем добавил бы группу Behaviors. Но это рабочий
Пример
import QtQuick 2.0
Rectangle {
width: 360
height: 360
property string state1:"OutMouse"
property string state2: "OutMouse"
property string state3: "OutMouse"
property string state4: "OutMouse"
Rectangle{
id:blueRec
width: parent.width
height: parent.height / 6
color: state1 === "InMouse" ? "blue" : "green"
MouseArea{
anchors.fill: blueRec
hoverEnabled: true
onEntered: state1 = "InMouse"
onExited: {
if (state1 === state2 || state3 || state4){
state1 = "InMouse"
}
if(state1 !== state2 || state3 || state4)
{
state1 = "OutMouse"
}
}
}
Text {
text: state1=== "InMouse"? qsTr("foo") :"bar"
anchors.centerIn: blueRec
}
Row{
width: parent.width
height: parent.height / 4
spacing: 2
anchors{
left: parent.left
verticalCenter: blueRec.verticalCenter
leftMargin: blueRec.width / 12
}
Rectangle{
id: rec1
height: parent.height;
width: height
color: {
if ( state3 === "InMouse")
return "gray"
if (state1 === "OutMouse")
return "transparent"
else
return "white"}
MouseArea{
id: rec1M
anchors.fill: parent
hoverEnabled: true
onEntered:{
state1 = "InMouse"
state2 = "InMouse"
}
onExited: state2 = "OutMouse"
}
}
Rectangle{
id: rec2
height: parent.height ;
width: height
color: {
if (state3 === "InMouse")
return "gray"
if (state1 === "OutMouse")
return "transparent"
else
return "white"
}
MouseArea{
id: rec2M
anchors.fill: parent
hoverEnabled: true
onEntered:{
state1 = "InMouse"
state3 = "InMouse"
}
onExited: state3 = "OutMouse"
}
}
Rectangle{
id: rec3
height: parent.height;
width: height
color:{
if (state4 === "InMouse")
return "gray"
if (state1 === "OutMouse")
return "transparent"
else
return "white"
}
MouseArea{
id: rec3M
anchors.fill: parent
hoverEnabled: true
onEntered:{
state4 = "InMouse"
state1 = "InMouse"
}
onExited: state4 = "OutMouse"
}
}
}
}
}
Ответ 3
Iv'e пробовал несколько вещей, но не представляется возможным одновременно навешивать на два MouseArea
. preventStealing
и propagateComposedEvents
, похоже, работают только при наличии события click. Но из внутреннего MouseArea
вы можете вызвать сигнал entered()
другого. Что-то вроде этого:
import QtQuick 2.1
Rectangle {
width: 500
height: 500
Rectangle {
width:300
height: 300
color: "red"
MouseArea {
id: big
anchors.fill: parent
hoverEnabled:true
onEntered: {
console.log("ENTERED BIG mousearea");
}
onExited: {
console.log("EXITED BIG mousearea");
}
}
Rectangle {
anchors.centerIn: parent
height: 100
width: 100
color: "green"
MouseArea {
anchors.fill: parent
hoverEnabled:true
onEntered: {
console.log("ENTERED small mousearea");
big.entered();
}
onExited: {
console.log("EXITED small mousearea");
big.exited();
}
}
}
}
}
Проблема заключается в том, что перед вызовом entered()
будет вызываться сигнал exited()
из содержащего MouseArea
. Поэтому вам может потребоваться "задержать" изменение состояния в exited()
, чтобы убедиться, что вы действительно хотите скрыть свои кнопки действий. Другим решением было бы сохранить текущую позицию мыши и скрыть кнопки ТОЛЬКО, если exited()
вызывается с помощью мыши на одной из ее границ.
Ответ 4
Попробуйте следующее:
- добавьте сигнал во внутреннюю область, которая испускается при вводе мыши.
- Подключите сигнал к внешней области.
- Сигнал заставляет внешнюю зону входить в зависание.
Выход мыши на обоих будет отменять состояние наведения. Когда вы перемещаете мышь с элементов управления, она должна работать правильно без дополнительного кода