How do I pass a MouseEvent parameter in a QML signal - qt

I'm trying to propagate the MouseArea signals to a parent object, but using MouseEvent as the parameter type causes an import error.
import QtQuick 2.0
import org.kde.plasma.core 2.0
Rectangle {
id: linkRect
signal clicked(MouseEvent mouse)
ToolTipArea {
id: tooltip
anchors.fill: parent
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: linkRect.clicked(mouse)
}
}
}

Use the var type like this:
signal clicked(var mouse)

Use QtObject instead of MouseEvent.
Also this works for KeyEvent parameter in KeyPressed event.
signal clicked(QtObject mouse)
Note: The QtObject is base of these classes.

Related

QT QML Accessing Attached Property From Another QML Object

main.qml:
import QtQuick 2.11
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
ApplicationWindow {
id: window
x: 200
y: 200
visible: true
Component {
id: firstViewComponent
FirstView {
id: firstView
}
}
StackView {
id: stackView
anchors.fill: parent
Component.onCompleted: push(firstViewComponent)
}
Timer {
interval: 1000
running: true
onTriggered: stackView.pop()
}
}
FirstView.qml:
Rectangle {
id: view
StackView.onDeactivating: console.log('view: view is deactivating')
ListModel {
id: aModel
ListElement {
name: 'Element 0'
}
ListElement {
name: 'Element 1'
}
}
ListView {
id: listView
model: aModel
delegate: Rectangle {
id: listViewDelegate
Connections {
target: view.StackView // <---- DOESN'T WORK
onDeactivating: console.log('delegate ' + index + ': needs to do some housekeeping now')
}
}
}
}
I have a view that is instantiated by a StackView in main.qml. The StackView attaches a signal StackView.onDeactivating to the view. Is there any way to attach to the signal from an object other than the one the signal is attached to? I need to do some cleanup in listViewDelegate when the view is popped.
I could have view emit its own signal, and have the delegate respond to that signal. But what I'm wondering is if there is a way to connect to the attached signal: StackView.onDeactivating from a different object (listViewDelegate).
Yes and no. The Qt documentation partially addresses this: A Note About Accessing Attached Properties and Signal Handlers
It is not possible to directly access the property from a child. Attached properties need to be explicitly read by the class providing them. For your example, the parent class (StackView) simply searches for all attached properties it does provide in the child item (FirstView) as soon as it gets added, and handles all found properties/signals etc. by connecting them internally to whatever logic provides them.
However, nothing prevents you from gettings the attached property from the parent item, as long as you refer to it by id:
sampleProp: view.StackView.someProperty
The thing is: This indirect access only works this way for properties and nor for signals, as you can't simply refer to the attached object via view.StackView - so sadly, you are stuck with forwarding the signal to the child elements indirectly by creating a second signal in the root item and emitting it when the attached signal gets emitted.

Combobox doesn't open popup if MouseArea is above it

I have a listview with a delegate that has MouseArea covering the whole of a delegate. In that MouseArea's onClick slot I specifically set
mouse.accepted = false
but the Combobox from QtQuick.Controls 1.4 that lives in that delegate still refuses to open its popup on clicks. I've tested that combobox should receive the click with:
ComboBox {
id: cbChapters
model: chapters
MouseArea {
anchors.fill: parent
onClicked: {
mouse.accepted = false
console.log("arrived")
}
}
}
And the click events do arrive into this inner mouse area, just not into the combobox itself it seems... what might be the problem?
Answering my own question:
Problem seems to be that MouseArea automatically accepts Pressed events and in the Combobox code itself there's this:
onPressed: {
if (!Settings.hasTouchScreen)
popup.toggleShow()
}
onClicked: {
if (Settings.hasTouchScreen)
popup.toggleShow()
}
So it seems like Clicked requires touchscreen to open the popup(which is not present on the desktop, obviously)
This leaves only Pressed to open the popup, but it's being suppressed at the uppermost MouseArea as it is not a composed event and propagateComposedEvents does nothing for it.
The solution could be :
1) to go through your mouse area chain and in each one of them set:
onPressed: {
mouse.accepted = false
}
2) call popup directly in "clicked" handler
ComboBox {
id: cbChapters
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
cbChapters.__popup.toggleShow()
}
}
}

Qt - How to connect signal from loader item, if loader source changes dynamically

I have an application which needs the screen to be switched between multiple available screens. I am checking if this is possible with loader in qml.
The issue i am facing is connecting signals from loaded item.
I use an application example in qt documentation and found CreateConnection in application qml cannot have if condition.
I also tried to make it signal slot connection in a function and call in on source change of loader, but that too did not work.
Application.qml
import QtQuick 2.0
Item {
width: 100; height: 100
Loader {
id: myLoader
source: "MyItem.qml"
}
Connections {
target: myLoader.item
// here i tried using if (myLoader.item == "qrc:MyItemOne.qml") , but can't use if
onChangeToSecond: {
myLoader.source = "MyItemTwo.qml"
}
onChangeToFirst: {
myLoader.source = "MyItemOne.qml"
}
}
}
MyItemOne.qml
import QtQuick 2.0
Rectangle {
id: myItem
signal changeToSecond()
width: 100; height: 100
MouseArea {
anchors.fill: parent
onClicked: myItem.changeToSecond()
}
}
MyItemTwo.qml
import QtQuick 2.0
Rectangle {
id: myItem
signal changeToFirst()
width: 100; height: 100
MouseArea {
anchors.fill: parent
onClicked: myItem.changeToFirst()
}
}
Someone knows any way to use loader for this, or loader should not be used for this?
Your code works fine if I use MyItemOne.qml as the initial value for the myLoader.source (Qt5.6.0). However, it will print out a warning:
QML Connections: Cannot assign to non-existent property "onChangeToFirst"
which happens because MyItemOne does not define the changeToFirst signal. The ignoreUnknownSignals property of Connections element can be used to suppress the warning, or both screens should define the same set of signals.
Loader can be used if it does not matter that the previous view is always fully unloaded when switching.

Using a Loader for a string of QML

In Qt 5.3 I've been using the Loader QML element for loading screens, loading the view from a QML file in the background. Now I'm trying to load a string of QML dynamically. Qt.createQmlObject enables me to do so, but I can't seem to get the Loader element to play along.
Seems like Loader only takes a URL (QUrl) or component (QQmlComponent), but Qt.createQmlObject creates an object (QObject).
I'm new to QML, but from my understanding components are reusable elements, similar to classes, and objects are the instances of those classes. I thus can't seem to wrap my head around why Loader wouldn't work with objects.
How can I show a loading screen while (asynchronously) parsing and initializing a string of QML?
Example QML code:
Item {
Rectangle {id: content}
Loader {id: loader}
Component.onCompleted: {
var obj = Qt.createQmlObject('import QtQuick 2.3; Rectangle {}', content);
loader.source = obj; // Throws error.
}
}
It's not possible using the current API. As Loader's documentation says, it loads objects via a URL that points to a QML file or a Component:
import QtQuick 2.0
Item {
Rectangle {
id: content
anchors.fill: parent
color: "grey"
Loader {
id: loader
sourceComponent: myComponent
anchors.fill: parent
anchors.margins: 40
}
}
property Component myComponent: Qt.createComponent("MyComponent.qml", Component.Asynchronous)
}
MyComponent.qml:
import QtQuick 2.2
Rectangle {
color: "red"
}

QtQuick 2 Pass function to elements

I have a QML element "Button" which has a MouseArea element inside.
What I want to do is to send a function to the item and then pass it to MouseArea:
Example:
Button{
id: smth
...
...
onClicked: console.log("Someone Clicked Me!")
}
And my element could be something like this:
Rectangle{
property var onClicked
...
MouseArea{
onClicked : parent.onClicked
}
}
I found out that I can pass the function like in native js without parentheses, but I think there is a way to implement it like MouseArea element does.
The usual way to handle this situation in QML is to let the Button emit a signal, which is then handled by the user of Button.
Button.qml:
Rectangle {
id: root
signal clicked
MouseArea {
anchors.fill: parent
onClicked: root.clicked();
}
}
Usage:
Button {
onClicked: console.log("Button was clicked!");
}

Resources