2017-08-15 213 views
1

当我调用QJSValue的调用函数时,我在JavaScript函数中发生崩溃。使用QJSValue调用时发生崩溃

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

我有什么需要注意的?

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

1 ??
2 QV4:对象::调用qv4object_p.h 372 0x765d5a8c
3 QJSValue ::呼叫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(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 
     } 
    } 
} 
+0

圣莫尔你在这里做什么,再次开始我的朋友。从PieChart的C++发出一个'response'信号,然后使用自动生成的QML信号处理函数'onResponse:'来执行一些Javascript。只要你认为你需要使用任何QJS类,你立即知道这种方法是不正确的。 –

+0

我认为即使它们很简单,提供头文件也是有用的。它将允许我们编译和修改你的代码。 –

+0

该代码基于来自QT饼图http://doc.qt.io/qt-5/qtqml-tutorials-extending-qml-example.html的示例应用程序。 我不想使用onResponse的原因是,有一个要求可以在QML中注册一个javascript函数作为回调。 – jernkuan

回答

0

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

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

你可以宣布这样的回调(绑定根回调):

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

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

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

相关问题