Cannot assign to non-existent property when creating signal and using that - qt

I want to create an signal so I have an qml file with name TestCreateSignal.qml
with content like this:
import QtQuick 2.0
Rectangle
{
color: "red"
width: 344
height: 233
signal sendMessage
MouseArea
{
onClicked:
{
sendMessage();
}
}
}
and i want to use this signal in another qml file with name TestUseSignal.qml
import QtQuick 2.0
Rectangle
{
TestCreateSignal
{
sendMessage: //Error is at this line
{
console.log("message sendded");
}
}
}
but i got error like this when i want to user that
qrc:/TestUseSignal.qml:5 Cannot assign to non-existent property "sendMessage"

According to the docs:
An object can be notified through a signal handler whenever a
particular signal is emitted. A signal handler is declared with the
syntax on<Signal> where <Signal> is the name of the signal, with the
first letter capitalized. The signal handler must be declared within
the definition of the object that emits the signal, and the handler
should contain the block of JavaScript code to be executed when the
signal handler is invoked.
In your case:
TestCreateSignal
{
onSendMessage:
{
console.log("message sendded");
}
}

Related

QML signal and slot between 2 different QML

I need to perform some actions in let's say main.qml according to button press in button.qml. Button inside of the button QML is inside of some custom object. Let's give it a name customObject. So customObject in button.qml looks like this:
customObject {
id:trialObject
signal backPagePressed()
Button {
id:button1
MultitouchArea {
onPressed:
{
trialObject.backPagePressed()
}
Now when I press the button, it emits backPagePressed(). My question is: How can I make a slot for this signal in main QML? I'm familiar to signal and slot mechanism in C++, but that does not work for QML. I made something like this in main.qml:
Loader
{
id:pageLoader
onBackPagePressed:
{
pageLoader.source =""
}
}
That part needs to delete the Loader's source so that it will go back to page before. However, I'm not sure about onBackPagePressed: ... How can I connect my signal backPagePressed, to the related part in my loader?
You should use a Connections object (documented here) together with the item property of the Loader:
Loader {
id: pageLoader
source: "CustomObject.qml"
}
Connections {
target: pageLoader.item
//Qt < 5.15
onBackPagePressed: pageLoader.source = ""
//Qt >= 5.15
function onBackPagePressed()
{
pageLoader.source = ""
}
}

QML Custom Button can't emit pressed signal cause it is not a function?

I am trying to implement a custom button which has press() and release() functions that i call when an expected key event is received. In these functions pressed() and released() signals are called. released() works perfectly but when pressed() is called an error is shown:
TypeError: Property 'pressed' of object CustomButton_QMLTYPE_3(0x78214d8) is not a function
My theory is that the QML can't differentiate the Button's bool pressed property and the pressed() signal. Is this a bug or am i doing something wrong? Here's what i have done:
This is the custom button qml file:
import QtQuick 2.10
import QtQuick.Controls 2.12
Button {
id: control
function press() {
down = true;
pressed();
}
function release() {
down = false;
released()
}
}
In the example below when the F3 key is pressed or released i call the button functions and i expect them to arrive to the Connections i made.
CustomButton {
id: customButton
width: parent.width
height: parent.height
Connections {
target: customButton
onPressed: {
console.log("Custom button pressed!\n");
}
onReleased: {
console.log("Custom button released!\n")
}
}
}
focus: true
Keys.onPressed: {
if(event.key === Qt.Key_F3 && !event.isAutoRepeat) {
console.log("F3 Key pressed!")
customButton.press()
}
}
Keys.onReleased: {
if(event.key === Qt.Key_F3 && !event.isAutoRepeat) {
console.log("F3 Key released!")
customButton.release()
}
}
Like i said release works but the press is problematic. I see these lines in the console:
qml: F3 Key pressed!
qml: press function called
file:///D:/Projects/QmlExamples/qml/fxMenu/button/CustomButton.qml:10: TypeError: Property 'pressed' of object CustomButton_QMLTYPE_3(0x78214d8) is not a function
qml: F3 Key released!
qml: release function called
qml: Custom button released!
If you want manually emit pressed signal, declare it in your Button object:
Button {
id: control
signal pressed;
signal released;
function press() {
down = true;
pressed();
}
function release() {
down = false;
released()
}
onPressedChanged: {
if (down) {
release();
} else {
press();
}
}
}
As you mentioned, there is also a boolean property named "pressed", so it looks like QML engine does not recognize your intentions.

How to send a signal from one qml to another

I cannot find a way to communicate from one qml file to the other one. I know there are many ways to send signals from qml to C++ slots and reverse, but all my research about signals between two different qml files failed.
So I would be glad if someone can tell me, how I have to solve this problem.
First of all a little abstracted example to understand the problem in a better way...
The first QML in basics looks like that:
//MyQML1.qml
Rectangle
{
id: idMyRec1
signal mySignalFromQML1()
Button
{
id: idMyButton1
onClicked:
{
idMyRec1.mySignalFromQML1(); //to send the signal
}
}
}
The 2nd one looks like this:
//MyQML2.qml
Rectangle
{
id: idMyRec2
Text{
id: idMyText2
text: "Hello World!"
onMySignalFromQML1: //to receive the signal from the other qml
{
idMyText2.text = "Good Bye World!";
}
}
}
So this button should change the text in my 2nd QML to "Good Bye World!" when clicked...but this doesn't work...are there any other ways to send signals from QML to another QML?! Or am I doing something wrong?
You don't communicate between qml files, the QML file is just a prototype, you communicate between the object instances.
// Rect1.qml
Rectangle {
id: rect1
signal mySignal
Button {
onClicked: rect1.mySignal()
}
}
// Rect2.qml
Rectangle { // Rect1.qml
property alias text: txt.text
Text {
id: txt
}
}
And then you create the objects:
Rect1 {
onMySignal: r2.text = "Goodbye world!"
}
Rect2 {
id: r2
}
There are other ways to make a connection, however, connections happen between object instances, not qml files. The objects don't have to be in the same qml file too, but initially for simple things they will rarely be in different files.
For me this works with Connections and signal in one qml file as follow:
import QtQuick 2.4
import QtQuick.Controls 1.2
Item {
id: item
width: 200
height: 200
signal sendMessage(string msg, int compId)
Button {
text: "SendMessage"
onClicked: sendMessage("hello",1)
}
Item {
id: item1
Connections {
target: item
onSendMessage: if(compId==1) { console.log("Hello by Comp 1") }
}
}
Item {
id: item2
Connections {
target: item
onSendMessage: if(compId==2) { console.log("Hello by Comp 2") }
}
}
}
Of course the items with the Connections can be also in different files.

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.

qml send a list/array from signal

how can i create an item that send signal with array of data(array of numbers),
and read it from another item?....
I don't know what you want to do exactly, but here is an example:
import QtQuick 1.0
Item {
// item with the data
Item {
id: otherItem
property variant numbers: [11, 22, 33]
}
// declare signal
signal mySignal(variant array);
// send mySignal when component is ready
Component.onCompleted: mySignal(otherItem.numbers);
// signal handler
onMySignal: console.log("mySignal: " + array)
}

Resources