【问题标题】:Updating a QML property from another Javascript Script (Canvas3D)从另一个 Javascript 脚本 (Canvas3D) 更新 QML 属性
【发布时间】:2016-04-06 15:49:34
【问题描述】:

我在从 QML 读取 javascript 变量时遇到问题。我知道这看起来很容易,但这是一个特例:

我正在使用 canvas3D 生成大量 3D 球体,并且由于实例很长,我想显示一个进度条。

为此,我已经这样做了:

import "test6.js" as GLCode

Item {
id: mainview
width: 1280
height: 768
visible: true



// THE PROGRESS BAR

ProgressBar {
    id : progressBar
    anchors.centerIn: parent
    value: canvas3d.progress
    z:1
}


//THE CANVAS3D (WebGL)
Canvas3D {
    id: canvas3d
    anchors.fill: parent
    focus: true

    property double progress:0 //MY VARIABLE I WANT TO UPDATE FROM test6.js


    property var list : []

    // Emitted when one time initializations should happen
    onInitializeGL: {
        GLCode.initializeGL(canvas3d);
    }

我的 canvas3d 中有一个属性名称 progress,我正在尝试从 test6.js 脚本修改它

在 initializeGL(canvas3d) 函数中,我每次添加球体时都会更新进度值:

for ( i = 0; i < spheresNum; i ++ ) {

    var x = list[i][0];
    var y = list[i][1];
    var z = list[i][2];
    drawSphere(x,y,z,i);
    canvas3d.progress = i/spheresNum*100;
}

现在,问题是我只有在 initializeGL() 结束时才能获得更新的进度值。现在是这样的:

Progress Bar to 0%
(Waiting for all the sphere to be instanciated)
(initializeGL() ends)
Progress Bar to 100%

这是没用的。我希望每次创建球体时让条形图移动。

你知道我该怎么做吗?

【问题讨论】:

    标签: javascript qt qml


    【解决方案1】:

    您只看到 0% 和 100% 是进度,因为在 QML 引擎响应 canvas3d.progress 的更改值并更新 progessBar.value 的值之前,initializeGL() 中的 for 循环已完全执行。 for循环和属性绑定从progessBar.value更新到canvas3d.progress在同一个线程中运行。

    解决这个问题的方法是只调用initializeGL()一步,然后让出CPU来更新进度。我的想法是使用一个单次计时器,该计时器自称为numSphere 次,并在第 i 个镜头中初始化第 i 个 spere。

    逐步初始化函数将在 test6.js 中定义如下:

    function initializeGLSphere(i) {
        var x = list[i][0];
        var y = list[i][1];
        var z = list[i][2];
        drawSphere(x,y,z,i);
    }
    

    Canvas3d 的实例之后,添加单次计时器:

    property int currentSphere = 0
    
    Timer {
        id: timer
        repeat: false
        interval: 0
        onTriggered: {
            GLCode.initializeGLSphere(currentSphere)
            ++currentSphere
            progessBar.progress = currentSphere / GLCode.numSpheres
            if (currentSphere < GLCode.numSpheres) {
                timer.restart()
            }
        }
    }
    

    定时器在onInitializeGL启动:

    onInitializeGL: timer.start()
    

    启动单次计时器意味着将一个事件放入主 Qt 事件循环。一旦定时器间隔到期,定时器就会触发。 0ms 的间隔只是意味着定时器触发并尽快执行onTriggered 定时器事件到达事件队列的前面(循环)。

    在处理定时器事件之间,事件队列也会给 QML 引擎一些时间来更新progressBar.progress 的属性绑定。因此,您应该会看到很多介于 0 和 100 之间的中间进度值。但是,您不会看到全部,因为在属性绑定更新发生之前可能会处理多个计时器事件。如果您想查看更多进度更新,只需增加计时器间隔即可。

    【讨论】:

      猜你喜欢
      • 2017-02-27
      • 2019-04-13
      • 1970-01-01
      • 2012-09-14
      • 1970-01-01
      • 1970-01-01
      • 2020-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多