Функция QML, вызванная из C ++, не может обновить элемент - PullRequest
0 голосов
/ 15 ноября 2018

Я вызываю функцию QML из C ++.Проблема в том, что функция QML не может обновлять элемент QML при вызове из C ++.ниже приведен код:

В main.qml:

import QtQuick 2.0

function myQmlFunction(msg) {
    console.log("Got message:", msg)
    textbox.text = msg
    return "some return value"
}

Text {
    id: textbox
    text: "nothing"
}

В main.cpp:

QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();

QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
    Q_RETURN_ARG(QVariant, returnedValue),
    Q_ARG(QVariant, msg));

qDebug() << "QML function returned:" << returnedValue.toString();
delete object;

Элемент textbox представляет собой обычный текст, а текствнутри него остается «ничто», вместо ожидаемого «Привет из C ++».

Есть идеи о том, как решить эту проблему или об успешной передаче аргументов из C ++ в QML?

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Спасибо за помощь, Я также отладил его, и textbox.text перезаписывался «Hello from C ++» без текста в обновляемом окне.

Как и предполагал eyllanesc, я создавал новый объект движка, отличный от уже отображенного окна. (созданный в другом месте кода)

после ссылки на тот же объект проблема была решена.

0 голосов
/ 16 ноября 2018

Код Lé

Qml

Я предполагаю, что данный qml-код фактически принадлежит MyItem.qml вместо main.qml.

Ваш файл Qml сгенерировалошибка времени компиляции.Функции следует размещать внутри объекта, например:

// MyItem.qml
import QtQuick 2.0

Text {
    id: textbox
    text: "nothing"

    function myQmlFunction(msg) {
        console.log("Got message:", msg)
        textbox.text = msg
        return "some return value"
    }
}

Я не уверен, как вы смогли скомпилировать ваш проект без генерации ошибки, но я предполагаю, что либо

  1. Ваша версия QtCreator / Qt отличается от моей (весьма маловероятная причина); или
  2. Вы пытались сделать свой код минимальным и изначально имели родителя.

Я уверен, что у вас достаточно понимания Qml, поэтому я 'Я не собираюсь углубляться в это.

C ++

На стороне C ++ мне пришлось возиться с отладочным выводом, чтобы увидеть, что не так.Вот мой main.cpp:

// main.cpp
#include <QApplication>
#include <QDebug>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QQuickItem>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);  // Qt requires an instance of QApplication


    QQmlEngine *engine = new QQmlEngine;

    QString projectPath = "/Users/user/full/path/to/your/project";  // I'm on a Mac, but replace
                                                    // with the appropriate path to your project

    //  QQmlComponent component(engine, "MyItem.qml");   // this didn't work for me and
                                      // set component.status() to QQmlComponent::Error

    QQmlComponent component(engine, projectPath + "/qml/MyItem.qml");  // use full path

    qDebug() << "Status:" << component.status();
    if (component.status() == QQmlComponent::Error)
        qDebug() << "Errors:" << component.errors();
    else if (component.status() != QQmlComponent::Ready)
    {
        qDebug() << "Component is not ready!";
        return 0;
    }

    QObject *object = component.create();
    if (!object) { qDebug() << "Object creation failed!"; return 0; }

    QQuickItem *item = qobject_cast<QQuickItem*>(object);   // adding this didn't change much
                                                     // but this could be crucial

    QVariant returnedValue;
    QVariant msg = "Hello from C++";

    bool success = QMetaObject::invokeMethod(item, "myQmlFunction",   // replace `object` with `item`
                                             Q_RETURN_ARG(QVariant, returnedValue),
                                             Q_ARG(QVariant, msg));

    if (success)
        qDebug() << "QML function returned:" << returnedValue.toString();
    else
        qDebug() << "QMetaObject::invokeMethod returned false";

    delete object;

    return 0;
}

Вывод

Вывод, полученный при успешной сборке, при успешном создании объекта был

Status: QQmlComponent::Status(Ready)
Object: MyItem_QMLTYPE_0(0x7f8d4ae8b640)
qml: Got message: Hello from C++
QML function returned: "some return value"

У меня нетеще проверил, изменился ли текст в вашем Qml textbox.(Не стал беспокоиться. Это потребует больше изменений в коде C ++, и этот ответ уже достаточно длинный. Я также был уверен, что ничего не пойдет не так, поэтому ¯ \ _ (ツ) _ / ¯).


Lé Non-Code

Что если я не хочу использовать необработанный путь к файлу?

Если вы meh об использованиинеобработанный путь к файлу (например, /Users/whoami/ugly/looking/path) в

QString projectPath = "/Users/user/full/path/to/your/project";

. Вы можете добавить его в файл .pro:

DEFINES += SOURCE_PATH=$$PWD

и установить projectPath в

QString projectPath = QT_STRINGIFY(SOURCE_PATH);

Эта идея была заимствована из ветки форума .


Предположения

На протяжении всего моего ответа я предположил , чтоиерархия вашего проекта похожа на

/./
 |- myProject.pro
 |- main.cpp
 |- qml/
    |- MyItem.qml

Важно то, что вы используете свой полный путь к элементу qml.Если вы do найдете другое, чтобы сослаться на него (возможно, используя QUrl?), Тогда do оставьте комментарий об этом.


Дополнительное чтение

Ознакомьтесь с разделом детали класса QQmlComponent и QQmlComponent::create функция-член .Прочитав их, я узнал, какие значения нужно отлаживать и на что обратить внимание.

...