QML Item.grabToImage在Repeater上返回空图像?

时间:2016-09-29 16:43:01

标签: c++ qt automated-tests qml qt5

我有一个QML应用程序,我希望通过自动状态和当前状态之间的自动比较来确定它。

首先,我想使用QML的TestCase.grabImage,但返回的QImage wrapper object不允许将其内容保存到必须(重新)生成比较图像的文件中。

然后我发现了QML的Item.grabToImage,它返回一个可以存储到文件的对象并给我实际的底层QImage对象。在编写包装器函数以获得阻塞版本之后,我可以生成简单QML Item的图像,如Rectangle及其嵌套版本。但是当使用更复杂的东西时

Repeater {
    id: rect
    model: 10
    width: 100
    height: 10

    delegate: Rectangle {
        color: "red"
        x: (width + 1)* index
        width: 5
        height: 10
    }
}

我只得到一个与转发器对象尺寸相同的空图像。

这是我写的用来抓图像的功能(小心,这是WIP!):

function grabToImage(item, timeoutInMilliseconds) {
    var result = null;
    item.grabToImage(function(image) {
        result = image;
    });
    waitForRendering(item, timeoutInMilliseconds);
    console.log("After waitForRendering ", result);
    // wait for result for exponentially increasing time until timeout is exceeded
    var waitInterval = 100;
    var remainingTimeout = timeoutInMilliseconds;
    while(result === null && remainingTimeout > 0) {
        var waitFor = Math.min(waitInterval, remainingTimeout);
        wait(waitFor);
        remainingTimeout -= waitFor;
        waitInterval *= 2;
    }
    return result;
}

所有Rectangle s'Component.completed信号在grabToImage代码运行之前被触发,因此它们似乎已被实例化。

**更新**

根据user2436719的要求,我附加了周围的调用代码:

import QtQuick 2.3
import QtTest 1.0

TestCase {
    name: "UI tests"
    id: tests
    when: windowShown

    function grabToImage(item, timeoutInMilliseconds) {
        var result = null;
        item.grabToImage(function(image) {
            result = image;
        });
        waitForRendering(item, timeoutInMilliseconds);
        // wait for result with exponentially increasing wait amounts until timeout is exceeded
        var waitInterval = 100;
        var remainingTimeout = timeoutInMilliseconds;
        while(result === null && remainingTimeout > 0) {
            var waitFor = Math.min(waitInterval, remainingTimeout);
            wait(waitFor);
            remainingTimeout -= waitFor;
            waitInterval *= 2;
        }
        return result;
    }

    Repeater {
        id: repeater
        model: 10
        width: 100
        height: 10

        delegate: Rectangle {
            color: "red"
            x: (width + 1)* index
            width: 5
            height: 10
        }
    }

    Rectangle {
        id: rect
        color: "blue"
        width: 100
        height: 10

        Rectangle {
            color: "red"
            x: 1
            width: 5
            height: 10
        }

        Rectangle {
            color: "red"
            x: 7
            width: 5
            height: 10
        }
    }

    function test_Problem() {
        grabToImage(repeater, 5000).saveToFile("repeater.png");
        grabToImage(rect, 5000).saveToFile("rectangle.png");
    }
}

生成以下图片:

repeater.png

Repeater

rectangle.png

Rectangle

1 个答案:

答案 0 :(得分:1)

您必须将Repeater括起来放入另一个元素(ItemRow ...)并在其上调用grabToImage。实际上,Repeater不是委托元素的父级:Repeater的父级是。

Window {
    visible: true
    width: 640
    height: 480

    function grabToImage(item, fileName) {
        item.grabToImage(function(image) {
            image.saveToFile(fileName);
        });
    }

    Row{
        id: row
        spacing: 2

        Repeater {
            id: repeater
            model: 10 

            delegate: Rectangle {
                color: "red"
                width: 5
                height: 10
            }
        }
    }

    Rectangle {
        id: rect
        color: "blue"
        width: 100
        height: 10
        y: 50

        Rectangle {
            color: "red"
            x: 1
            width: 5
            height: 10
        }

        Rectangle {
            color: "red"
            x: 7
            width: 5
            height: 10
        }
    }

    Component.onCompleted:  {
        grabToImage(row, "repeater.png");
        grabToImage(rect, "rectangle.png");
    }
}