Как setContextProperty() не работает в этой ситуации?

У меня есть три класса, созданные на С++ как Window, PropertyList и MyParams, и я хочу передать эти два класса PropertyList и MyParams в qml.

class Window
{
public:
    PropertyList* getPropertyList();
private:
    PropertyList* propertyList;
};

class PropertyList : public QObject
{
    Q_OBJECT
public:
    MyParams* getMyParams();
    Q_INVOKABLE void test();

private:
    MyParams* myParams;
};

class MyParams : public QObject
{
    Q_OBJECT
public:
    Q_INVOKABLE void test();
};

int main(int argc, char *argv[])
{
    Window* window = new Window();
    PropertyList* propertyList = window->getPropertyList();
    MyParams* myParam = propertyList->getMyParams();

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty(QStringLiteral("myParams"), myParam);

    engine.rootContext()->setContextProperty(QStringLiteral("propertyList"), propertyList);
}

Почему это работает:

engine.rootContext()->setContextProperty(QStringLiteral("propertyList"), propertyList);

И это не удается:

 engine.rootContext()->setContextProperty(QStringLiteral("myParams"), myParam);

Это потому, что я объявляю PropertyList как Q_OBJECT? И как я могу это исправить? Большое спасибо.

propertyList.test() может быть вызван успешно, в то время как myParams.test() не может быть вызван и привел к сбою qml.

Пожалуйста, покажите нам MyParams. Это QObject?

Hubi 22.05.2019 12:52

@Hubi да, я поставил Q_OBJECT в определение класса

stephen 22.05.2019 12:53

Как это не удается? Вы получаете ошибку времени выполнения?

user6556709 22.05.2019 12:55

@user6556709 user6556709 ах, я добавлю больше кода, чтобы показать, как это терпит неудачу

stephen 22.05.2019 12:55

QML обычно не дает сбоев без ошибки времени выполнения, и ваше описание не соответствует коду. Оба реализованы как QObjects, и это необходимо для обоих. У вас не может быть Q_INVOKABLE, если это не QObject. Вы можете сделать их свойствами без, но вам нужно зарегистрировать типы.

user6556709 22.05.2019 13:19

@user6556709 user6556709 что вы имеете в виду под этим нужно для обоих. Я объявляю MyParams и PropertyList как Q_OBJECT

stephen 22.05.2019 13:22

Этот пример не будет компилироваться. Обратите внимание: stackoverflow.com/help/репрекс

Hubi 22.05.2019 13:56
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
1
7
488
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не вижу никаких проблем в вашем примере кода, потому что он неполный (считайте: https://stackoverflow.com/help/репрекс).

Тем не менее я реализовал решение для вас. Надеюсь, это поможет. (Предупреждение: вокруг класса Window будут утечки памяти, но это должно помочь понять привязку C++ и Qml)

Вот ваш PropertyList.h:

#ifndef PROPERTYLIST_H
#define PROPERTYLIST_H

#include "myparams.h"

#include <QObject>

class PropertyList : public QObject
{
    Q_OBJECT
public:
    explicit PropertyList(QObject *parent = nullptr) : QObject (parent) { }

    MyParams* getMyParams()
    {
        return  myParams;
    }

    Q_INVOKABLE void test()
    {
        qDebug() << "PropertyList test";
    }

private:
    MyParams* myParams = new MyParams();
};

#endif // PROPERTYLIST_H

Вот ваш MyParams.h:

#ifndef MYPARAMS_H
#define MYPARAMS_H

#include <QObject>
#include <QDebug>

class MyParams : public QObject
{
    Q_OBJECT
public:
    explicit MyParams(QObject *parent = nullptr) : QObject (parent) { }

    Q_INVOKABLE void test()
    {
        qDebug() << "MyParams test";
    }
};

#endif // MYPARAMS_H

Вот ваш main.cpp:

#include "propertylist.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQmlContext>
#include <QDebug>

class Window
{
public:
    PropertyList* getPropertyList()
    {
        return propertyList;
    }

private:
    PropertyList* propertyList = new PropertyList(nullptr);
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    Window* window = new Window();
    PropertyList* propertyList = window->getPropertyList();
    MyParams* myParam = propertyList->getMyParams();

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty(QStringLiteral("myParams"), myParam);

    engine.rootContext()->setContextProperty(QStringLiteral("propertyList"), propertyList);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
    {
            return -1;
    }

    return app.exec();
}

Вот ваш main.qml:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.centerIn: parent
        Button {
            text: "myParams"
            onClicked: {
                myParams.test()
            }
        }

        Button {
            text: "propertyList"
            onClicked: {
                propertyList.test()
            }
        }
    }
}

Спасибо, я нашел свою проблему, забыл инициализировать объект myParam :)), сбил меня с толку.

stephen 22.05.2019 14:35

Рад помочь вам. Пожалуйста, установите этот ответ как «правильный ответ» и проголосуйте за него ;-). Так что вы тоже можете помочь другим.

Hubi 22.05.2019 14:44

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