I'm trying to have my QML application react to the forwards/back buttons (sometimes labeled as buttons 4/5) that are on some mice. It seems a mouse area/event only allows signals on the three main mouse buttons.
Is there any way to handle these buttons in QML?
If you look at the list of predefined mouse buttons you'll see that there is a ForwardButton and BackButton. The only "trick" you need to listen for these buttons in a QML MouseArea is to set the acceptedButtons property.
You could either set it to only listen for forward and back:
acceptedButtons: Qt.ForwardButton | Qt.BackButton
Or you could just listen for any mouse button:
acceptedButtons: Qt.AllButtons
Putting it all together, your MouseArea could look something like this:
MouseArea {
acceptedButtons: Qt.AllButtons
onClicked: {
if (mouse.button == Qt.BackButton) {
console.log("Back button");
} else if (mouse.button == Qt.ForwardButton) {
console.log("Forward button")
}
}
}
Related
I have a simple task. I want to find out whether the left or right mouse button was pressed inside TapHandler.onSingleTapped:
TapHandler {
acceptedButtons: Qt.LeftButton | Qt.RightButton
onSingleTapped: function(eventPoint) {
// Print if it was left or right button
}
}
The supplied eventPoint does not contain this information. Where can I get this info?
Here you go, taken from TapHandler tapped() documentation:
TapHandler {
acceptedButtons: Qt.LeftButton | Qt.RightButton
onSingleTapped: function(eventPoint) {
console.log("tapped", eventPoint.event.device.name,
"button", eventPoint.event.button,
"#", eventPoint.scenePosition)
}
}
But you could also use a dedicated TapHandler for each button type: QtWS17 - Pointer Handlers for fluid applications in Qt Quick
I wanted to make a borderless window and add borders when mouse is inside that window/remove them when mouse is outside. So i added to my ApplicationWindow
anchors.fill: parent
hoverEnabled: true
onEntered: {
if(root.isBorderLessMode)
if(!(root.flags & Qt.FramelessWindowHint))
root.flags |= Qt.FramelessWindowHint;
}
onExited: {
if(root.isBorderLessMode)
if((root.flags & Qt.FramelessWindowHint))
root.flags &= ~Qt.FramelessWindowHint;
}
}
Problem is when i move mouse inside that window application hangs for large amount of time and it is adding/removing border during that time. Why functions aren't called only once on enter and on exit?
The QT documentation has this tutorial.
I initially followed it exactly, and it works. I then made two modifications:
I replaced the ListView with a GridView (that works without #2).
I attempted to add a ToolButton to my delegate inside the Rectangle "content" like so:
Rectangle {
id: content
ToolButton {
id: toolButton
icon.color = "transparent"
icon.source = "image://Loader/iconName"
}
Drag.active: dragArea.held
Drag.source: dragArea
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
}
This does not work, the ToolButton appears to be processing the mouse movements and not propagating the messages (I can click the button, but I can not drag it)? This is actually somewhat expected to be honest.
So that said, does anyone have a good way of dragging ToolButtons around? Or is it just accepted that you can't do that? I have tried various combinations of Rectangles and MouseAreas but I can't seem to do one without breaking the other (ie either the drag fails or the button fails).
You can move the MouseArea as a child of the ToolButton to manage the drag with pressAndHold, and propagate the click to keep the button behavior:
Rectangle {
id: content
ToolButton {
id: toolButton
// bind the visual state of the button to the MouseArea
background: Rectangle {
color: marea.pressed
? Qt.darker("blue")
: marea.containsMouse
? Qt.lighter("blue")
: "blue" // use your desired colors
}
MouseArea {
id: marea
property bool held: false
drag.target: held ? content : undefined
drag.axis: Drag.YAxis
anchors.fill: parent
hoverEnabled: true
onPressAndHold: held = true
onReleased: held = false
onClicked: toolButton.clicked() // propagate clicked event to the ToolButton
}
}
// ...
}
I was wondering if there's any way for ListView to behave like a desktop control and not react with scrolling to mouse dragging?
I know about the interactive property, but I still want the ListView to react to clicks, mouse wheel, arrow keys, and have a ScrollBar.
For starters, setting interactive to false will pretty much immobilize the view.
There is a keyNavigationEnabled property which doesn't seem to work at this moment(this critical bug).
So will need to do a little extra work to get it to work as you want:
MouseArea {
anchors.fill: ll
onWheel: ll.flick(0, wheel.angleDelta.y * 5)
}
ListView {
id: ll
model: 50
width: 50
height: 200
spacing: 5
focus: true
interactive: false
boundsBehavior: Flickable.StopAtBounds
Keys.onPressed: {
if (event.key === Qt.Key_Up) flick(0, 500)
else if (event.key === Qt.Key_Down) flick(0, -500)
}
delegate: Rectangle {
width: 50
height: 50
color: "red"
MouseArea {
anchors.fill: parent
onClicked: console.log("clicked")
}
}
}
Interactivity is disabled, key navigation is implemented manually, and a background MouseArea is used to capture wheel events. Note that you don't have to do anything special to enable clicking on items for a non-interactive view, it works regardless of the view is interactive or not.
I have several QML Items that all have Mouse Areas.
What I want to achieve is:
Click one of the items and start tracking the mouse
Add every other Item that the mouse enters into a list
End the tracking once the mouse is released
Sample Code:
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
visible: true
width:500; height: 200;
Rectangle{
anchors.left: parent.left
color: 'red'
width: 200; height: 200;
MouseArea {
anchors.fill: parent
hoverEnabled: true
onReleased: console.log('onReleased red')
onEntered: console.log('onEntered red')
onPressed: {
console.log('onPressed red')
mouse.accepted = false
}
}
}
Rectangle{
anchors.right: parent.right
color: 'blue'
width: 200; height: 200;
MouseArea {
anchors.fill: parent
hoverEnabled: true
onReleased: console.log('onReleased blue')
onEntered: console.log('onEntered blue')
onPressed: console.log('onPressed blue')
}
}
}
Expected behaviour:
Click one Rectangle
Get on entered event if I enter the other element
Get the Released event
The sample code has both Version I tried, with and without accepting the mousePressed event.
What happens is:
If I press the mouse over one rectangle I do not get the onEnter event for all my other rectangles.
If I do not accept the onPressed event, I get the onEnter Events but not the onReleased event.
Note:
I already found this Answer which uses a DropArea as workaround which is not what I want to use if there is any other solution.
Even though the Example may look like Drag&Drop it is not what I want.
Please see the "What I want to achieve" at the top of this Question.
You will not be able to achieve what you want just using standart MouseArea components. Standart QML components are kinda limited in their functionality.
What you have to do is to create your own MouseArea component through QML extension.
In our project we also encountered lots of problems with mouse handling, so how we managed to do it was:
Subclassed QQuickItem, and inside of this class we just tracked the mouse movement, and mouse buttons states. One important thing wass to install EventFilters defined by this class.
In QML, created a Simple Component that Checks if mouse is inside of currrent component.
If you need, i could post also a code here so you have an idea.
The implementation is not the prettiest, but it works