2

I started writing application in QML (using QtQuick 1.1 with Qt 4.8.1) and I have a few questions about signals. In my project there are following files:

main.qml:

Rectangle {
    signal sigExit()
    width: 800
    height: 600
    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            sigExit();
            Qt.quit();
        }
    }
    Button
    {
        x: 10
        y: parent.height-height-5
        text: "someText"
    }
}

Button.qml:

Rectangle {
    signal buttonsig()
    width: 60
    //(...)
    MouseArea
    {
        anchors.fill: parent
        onClicked: buttonsig();
    }
}

When I want to connect signal from main.qml to C++ slot, I do:

main.cpp :

QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer.setMainQmlFile(QLatin1String("qml/MyProject/main.qml"));
viewer.showExpanded();

MyClass* obj = new MyClass;
QObject* item = qobject_cast<QObject*>(viewer.rootObject());
QObject::connect(item, SIGNAL(sigExit()), obj, SLOT(onExitWindow()));

and it works. But what when I want to connect sigbutton() from Button.qml to C++ slot? It will be something like that?

QObject *rect = item->findChild<QObject*>("Button");
QObject::connect(rect, SIGNAL(buttonsig()), obj, SLOT(onExitWindow()));

And the second issue: how can I connect sigbutton() to main.qml (for example, I want to change position of my buttons after clicking them)?

Nejat
  • 31,784
  • 12
  • 106
  • 138
trivelt
  • 1,913
  • 3
  • 22
  • 44

2 Answers2

1

You will also need to have the objectName property of your Button item if you want to access it :

Button {
    id: myButton
    objectName: "myButton"
    x: 10
    y: parent.height-height-5
    text: "someText"
}

Now you can access it by :

QObject *rect = item->findChild<QObject*>("myButton");

Regarding the second question, you can use Connections object to connect buttonsig() to some QML signal handler in main.qml :

Rectangle {
    signal sigExit()
    width: 800
    height: 600

    Connections{
        target: myButton
        onButtonsig :
        {
            ...
        }
    }

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            sigExit();
            Qt.quit();
        }
    }
    Button
    {
        id: myButton

        x: 10
        y: parent.height-height-5
        text: "someText"
    }
}

Note that the signal handler's name should be on<Signal> (First letter of signal letter Capital). Also Button should have an id to address it in Connections.

Nejat
  • 31,784
  • 12
  • 106
  • 138
  • Thanks! And what about second question? Is there a possibility of connecting signal from one QML file to slot (or something similar) in another QML file? – trivelt Oct 11 '14 at 11:49
1

Accessing loaded qml elements, casting them and connecting their signals to your C++ slots is perferctly possible. But this method should be avoided in your production code. See this warning from Qt docs.

So what's the way to call a C++ slot from qml side? You can register the object whose slot needs to be called with qml engine as a context property. Once registered, these context properties can be accessed anywhere from QML side.

Slots of objects registered as context properties can be called directly in your signal handler in QML example: onClicked:{<contextPropertyName>.<slotName>()}

Or, you can connect a QML signal with context property object's slot directly using Connections type. Please see this documentation

For details about registering context properties, please see Embedding C++ objects into QML with context properties.

If you want to see some examples, see my answers to these questions. Qt Signals and Slots - nothing happens and Setting object type property in QML from C++

Community
  • 1
  • 1
Programmer
  • 1,290
  • 2
  • 12
  • 16