使用QJSValue调用时崩溃

时间:2017-08-15 16:46:41

标签: qt qml

当我调用QJSValue的调用函数时,我的JavaScript函数经常崩溃。

我有一个正在运行的线程,将QMetaObject invokeMethod调用为QueuedConnection而不是DirectConnection,以确保在主ui线程中调用该方法。然后调用的此方法将随后触发QJSValue JavaScript函数。 JavaScript函数修改QML中的一些UI元素。当没有对UI元素进行修改时,我注意到没有崩溃。

有什么问题需要注意吗?

在Raspberry PI3上运行大约10小时后崩溃。

  

1 ??   2 QV4 :: Object :: call qv4object_p.h 372 0x765d5a8c
  3 QJSValue :: call qjsvalue.cpp 670 0x765d5a8c
  4 ?? 0x70352fb8

这是第6章插件修改后的代码

PieChartWorker类

PieChartWorker::PieChartWorker(QObject *parent):
    QThread(parent)
{
}

void PieChartWorker::run()
{
    QString text;
    while(1) {
    QString textb = text.sprintf("The answer to the meaning of life is %i", std::rand()%100);

        QMetaObject::invokeMethod(this,
                                  "responseInternal",
                                  Qt::QueuedConnection,
                                  Q_ARG(QString, QString::fromLocal8Bit("hello")),
                Q_ARG(QByteArray, textb.toLocal8Bit()));
        QThread::msleep(50);
    }
}

void PieChartWorker::responseInternal(const QString question, const QByteArray& answer)
{
    emit response(question, answer, callback);
}

void PieChartWorker::registerCallback(const QJSValue callback)
{
    this->callback = callback;
    start();
}

PieChart课程

PieChart::PieChart(QQuickItem *parent)
    : QQuickItem(parent)
{

    PieChartWorker* worker = new PieChartWorker();
    worker->moveToThread(&m_thread);

    connect(&m_thread, &QThread::finished, worker, &QObject::deleteLater);

    connect(this, &PieChart::registerCallback, worker, &PieChartWorker::registerCallback);
    connect(worker, &PieChartWorker::response, this, &PieChart::response);
    m_thread.start();
}

void PieChart::response(const QString question, const QByteArray& answer, QJSValue callback)
{
    if (callback.isCallable()) {
        QJSValueList args;
        args << question;
        args << QString::fromLocal8Bit(answer);
        callback.call(args);
    }
}

app.qml

import QtQuick 2.0
import Charts 1.0

Item {
    width: 300; height: 200
    Text {
        id: label
        text: "hello"
        x:100; y:100
        color: 'black'
    }
    PieChart {
        anchors.center: parent
        width: 100; height: 100

        Component.onCompleted: {
            registerCallback(updateResult)
        }

        function updateResult(question, answer) {
            console.log(question)
            console.log(answer)
            label.text = answer
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我已经在这个问题上工作了几个小时,最后,我解决了它。

首先。 JS函数有一个像context这样的概念,你的回调使用label,它是一个外部UI对象。 因此,当从C ++调用它时,JS引擎不知道label是什么,因为context已更改。

你可以像这样声明回调(用root绑定回调):

Item{
    id: root
    function reload() {
        X.send(request, root.callback)
    }
    function callback(data) {
        console.log(data, root)
    }
}

其次。如果修改回调中的UI属性,则必须确保在主循环中调用它。像label.text=...一样,你必须在主循环中完成。

您可以使用QCoreApplication::postEvent在主循环中调用QJSValue。