QML: Button inside MouseArea does not pass mouse hover events - qt

There is a button inside MouseArea:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
id: background
anchors.fill: parent
color: mouseArea.containsMouse ? "red" : "green"
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: console.log("onEntered")
onExited: console.log("onExited")
//onPositionChanged: console.log("position", mouse.x, mouse.y)
Button {
id: button
anchors.centerIn: parent
width: 200
height: 100
}
}
}
In Qt5, if you hover the mouse over the button, the containsMouse property will remain true and the onExited and onEntered handlers will not be called.
If you switch to Qt6, then when you move the mouse over the button, the onExited and onEntered handlers are called and containsMouse becomes false.
I need hover events behavior in Qt6 the same as in Qt5. Is it possible?

Related

QML MouseArea: how to propagate mouse events to other mouse areas?

I have a complex dialog that contains lots of controls in complex layouts. I need to add a cursor marker: vertical line which is drawn above this dialog and should follow the mouse cursor.
I do not understand how to implement this.
Simplified sample code:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
visible: true
width: 640
height: 480
Button {
anchors.centerIn: parent
width: 100
height: 50
text: "Button"
highlighted: hovered
}
Rectangle {
id: cursorMarker
width: 1
color: "black"
anchors.top: parent.top
anchors.bottom: parent.bottom
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPositionChanged: {
cursorMarker.x = mouse.x
}
}
}
In this sample, MouseArea placed above the button and intercepts all mouse messages. So the button is not highlighted when the mouse cursor moved above it. In case when MouseArea placed below the button then the cursor marker is not positioned correctly when mouse moved over the button.
But I need both: the cursor marker is positioned correctly above the whole dialog and the button working correctly.
How to solve this problem?
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
visible: true
width: 640
height: 480
property int mousePosX : 0
property int mousePosY : 0
Button {
anchors.centerIn: parent
width: 100
height: 50
text: "Button"
// Test if the mouse is within the Button
highlighted: mousePosX > x && mousePosX > y && mousePosX < x + width && mousePosY < y + height
}
Rectangle {
id: cursorMarker
x: mousePosX
width: 1
color: "black"
anchors.top: parent.top
anchors.bottom: parent.bottom
}
MouseArea {
id: mouse
anchors.fill: parent
hoverEnabled: true
onPositionChanged: {
mousePosX = mouse.x
mousePosY = mouse.y
}
}
}
I suggest the following (Not exactly what you are asking, but another approach to implement the same) :
Store the mouse pos in some vars.
Then check if current mouse pos is within the button objects (by seeing if it lies within the bounding box of that button)

How to achieve click an area outside the TextField to make the TextField lose focus?

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
TextField {
id:textField
width: 130
height: 50
}
Button {
anchors.right: parent.right
text: "lose Focus"
}
}
why textField don't lose Focus when Button Click?
How to achieve click an area outside the TextField to make the TextField lose focus?
The simplest way using your existing code is to force active focus on another item when the button is clicked:
Button {
anchors.right: parent.right
text: "lose Focus"
onClicked: forceActiveFocus()
}
To make the TextField lose focus when clicking the area outside of it, you can do something similar with MouseArea:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea {
anchors.fill: parent
onClicked: forceActiveFocus()
}
TextField {
id: textField
width: 130
height: 50
}
}
This item needs to be below (i.e have a lower Z value than) other items in the scene. You can also make it a parent of the other items to achieve this:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea {
anchors.fill: parent
onClicked: forceActiveFocus()
TextField {
id: textField
width: 130
height: 50
}
}
}
If you're using Qt Quick Controls 2, you can use the focusPolicy property on e.g. Pane:
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Pane {
anchors.fill: parent
focusPolicy: Qt.ClickFocus
}
TextField {
id: textField
width: 130
height: 50
}
}

How to managment the position of the item in the ListView during the scrolling

I have the list view. When I scroll items the top element can stop any position and can be seen half height. enter image description here
But I need that after scrolling stop the top element can be seen full height.enter image description here
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.12
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Scroll")
ColumnLayout {
anchors.fill: parent
RowLayout {
id: buttonsRow
Button {
text: "Open dump file"
}
Button {
text: "Copy raw data to clipboard"
}
}
ListView {
id: listView
flickableDirection: Flickable.VerticalFlick
boundsBehavior: Flickable.StopAtBounds
model: 100
clip: true
delegate: ItemDelegate {
text: modelData
Rectangle
{
width: parent.width - 5
height: parent.height - 5
color: "green"
}
}
Layout.fillWidth: true
Layout.fillHeight: true
ScrollBar.vertical: ScrollBar {}
}
}
}
Use the snapMode property:
ListView {
snapMode: ListView.SnapToItem
// ...
}

Manage part of the window with a stackview within splitview

I designed my main interface with two levels of splitview in order to get five rectangle areas.
Here is my code :
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
import "../geoforms"
SplitView {
id: splitView0
orientation: Qt.Horizontal
// anchors.fill: parent
SplitView {
id: splitView1
width: window.width/10*8
height: 900
Layout.minimumWidth: window.width/10*2
Layout.maximumWidth: window.width/10*8
orientation: Qt.Vertical
MapRectangle{
id:newMapRectangle
height: 300
width: 700
anchors.top: parent.top
anchors.left:parent.left
anchors.right: parent.right
Layout.fillHeight: true
}
FPArea{
id: flightPlanArea
}
}
SplitView {
id: splitView2
width: 100
height: 100
orientation: Qt.Vertical
FPMap{
id: newFlightPlanMap
}
AltitudePM{
id: newAltitudePlanMap
}
IME{
id: newButtonArea
color: "grey"
mainGridProp.rows : 3
mainGridProp.columns: 2
mainGridProp.spacing: 20
}
} //Splitview2
} //Splitview
I need to manage a stackview for the splitview1.MapRectangle area. For that, I added a stackview in the code, like this :
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
Item{
id: itemMapRectangle
Rectangle {
id: mapRect
color: "#4c4e50"
border.color: "#404244"
border.width: 3
}
StackView{
id: stackView
anchors.fill: parent
focus: true
initialItem: Item {
id: page
}
}
}
The result is weird.
Furthermore, documentation says : "Using StackView in an application is typically a simple matter of adding the StackView as a child of a Window.". So I'm afraid stackview to be only bindable to a window.
Is there a way to link it to part of a window via a splitview ? If yes, is it possible to have multiple stackview for different areas of the interface ?
SplitView is a regular control as all other QML controls so you can set size/anchors as you want. But SplitView implements attached properties of Layout so you should use its properties to set size of inner elements. For example:
SplitView {
anchors.fill: parent
orientation: Qt.Horizontal
StackView {
Layout.fillHeight: true
Layout.minimumWidth: 200
initialItem: Rectangle {
color: "orange"
}
}
StackView {
Layout.fillHeight: true
Layout.fillWidth: true
initialItem: Rectangle {
color: "yellow"
}
}
}

Not able to handle child rect mouse events in QML

I have a parent rectangle on top of it there is a child rectangle, both rectangles having mouse events but child rectangle is not taking any mouse event always parent rectangle is handling.
main.qml
import QtQuick 2.3
import QtQuick.Controls 1.2
ApplicationWindow {
visible: true
width: 500
height: 500
title: qsTr("Hello World")
Rectangle{
id: outerrect
color: "green"
anchors.fill: parent
Rectangle{
id: innerrect
width: 100
height: 100
color: "lightblue"
anchors.centerIn: parent
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
console.log("child")
}
}
}
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
console.log("parent")
}
}
}
}
Issue:
Not able to handle child rectangle mouse events
See the example and explanation for the property propagateComposedEvents of MouseArea QML Type
So, if you want to handle the click only by the child rectangle you can change the order of the MouseArea block in the parent and the child Rectangle block. It changes the order of handling events by blocks.
To activate both handlers the top object should have propagateComposedEvents: true property and also mouse.accepted = false should be set in the onClicked handler, for example:
MouseArea{
anchors.fill: parent
propagateComposedEvents: true
hoverEnabled: true
onClicked: {
mouse.accepted = false
console.log("parent")
}
}

Resources