Обработка сигналов через несколько QML

Я только начал изучать программирование на Qt и обнаружил, что борюсь с механизмом сигналов и слотов, создавая простое тестовое приложение.

У меня есть два файла QML: main.qml и grocery.qml.

У меня есть заголовочный файл, который управляет сигналами и слотами приложения:

applicationamanger.h

#ifndef APPLICATIONMANAGER_H
#define APPLICATIONMANAGER_H
#include <QObject>
#include <QDebug>
class ApplicationManager : public QObject
{
    Q_OBJECT
public:
    explicit ApplicationManager(QObject *parent = 0);

signals:
    void newGroceryItem();

public slots:
    void addGroceryItem();
};
#endif // APPLICATIONMANAGER_H

Пользователь запускает приложение на main.qml и при нажатии кнопки загружает grocery.qml

На grocery.qml у меня есть изображение, которое может быть нажата пользователем и испускает сигнал newGroceryItem()

MouseArea {
    id: okBtnClkd
    anchors.fill: parent
    Connections {
        onClicked: {
            newGroceryItem()
        }
    }
}

И основное приложение main.cpp соединяет сигналы, но говорит, что не может найти сигнал newGroceryItem(), поскольку он не принадлежит main.qml. Итак, мой вопрос, как я могу установить соединение со слотом addGroceryItem() из вторичного файла qml grocery.qml?

РЕДАКТИРОВАТЬ: В соответствии с просьбой, вот содержимое main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QQmlContext>
#include "applicationmanager.h"
int main(int argc, char *argv[]){
  QGuiApplication app(argc, argv);
  QQmlApplicationEngine engine;
  engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

  QObject *topLevel = engine.rootObjects().value(0);
  QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
  ApplicationManager applicationManager;
  QObject::connect(window, SIGNAL(newGroceryItem()), &applicationManager, SLOT(addGroceryItem()));

  return app.exec();
}

И содержимое grocery.qml

import QtQuick 2.5
import QtQuick.Controls 1.4

ApplicationWindow {
    //Declaration of signals.
    signal newGroceryItem()

    width: 300
    height: 400
    visible: true
    TextField {
        id: product
        x: 14
        y: 111
        width: 270
        height: 22
    }
    Text {
        id: text1
        x: 14
        y: 81
        width: 124
        height: 24
        text: qsTr("Product")
        font.pixelSize: 20
    }
    Image {
        id: okBtn
        x: 99
        y: 290
        width: 100
        height: 100
        source: "img/main/okBtn.png"

        MouseArea {
            id: okBtnClkd
            anchors.fill: parent
            Connections {
                onClicked: {
                    newGroceryItem()
                }
            }
        }
    }
}

1 ответ

Любой метод QObject-приобретенный тип доступен из кода QML, если он:

  • публичный метод помечен с Q_INVOKABLE макрос
  • метод, который является публичным слотом Qt

Таким образом, есть два способа доступа addGroceryItem(), Первый заключается в использовании Q_INVOKABLE макрос следующим образом:

class ApplicationManager : public QObject
{
    Q_OBJECT
public:
    explicit ApplicationManager(QObject *parent = 0);
    Q_INVOKABLE void addGroceryItem();
};

Второй способ заключается в использовании public slots следующее:

class ApplicationManager : public QObject
{
    Q_OBJECT
public:
    explicit ApplicationManager(QObject *parent = 0);
public slots:
    void addGroceryItem();
};

Если вы создаете свой объект класса в C++, тогда вы должны установить объект в качестве данных контекста для main.qml следующее:

 int main(int argc, char *argv[]) {
     QCoreApplication app(argc, argv);

     QQmlEngine engine;
     ApplicationManager app;
     engine.rootContext()->setContextProperty("applicationManager", &app);
     QQmlComponent component(&engine, QUrl::fromLocalFile("main.qml"));
     component.create();

     return app.exec();
 }

Теперь вы можете получить доступ к ApplicationManager объект, созданный в main.cpp от main.qml следующее:

MouseArea {
    id: okBtnClkd
    anchors.fill: parent
    onClicked: {
        applicationManager.addGroceryItem();
    }
}

Для получения дополнительной информации см. Здесь.

Другие вопросы по тегам