QML:文档完全加载时触发的事件

时间:2015-01-12 10:01:30

标签: c++ qt qml qtquick2

我现在正在使用一个应用程序加载QML文件并制作一个窗口的屏幕截图。 这就是它现在的样子:

QQmlApplicationEngine engine;
engine.loadData(data);
QQuickWindow *rootObject = qobject_cast<QQuickWindow *>(engine.rootObjects().first());

QImage image = rootObject->grabWindow();
image.save("window.png","PNG",90);

在这种情况下,data只是简单的QML结构:

import QtQuick 2.3
import QtQuick.Window 2.2

Window {
    visible: true
    width: 360
    height: 360

    Text {
        anchors.centerIn: parent
        text: "Hello, world!"
    }
    MouseArea {
         anchors.fill: parent
         //onClicked: someSingleton.makeScreenshot();
    }
    Component.onCompleted: someSingleton.makeScreenshot();
}

但我从QQuickWindow::grabWindow()获得的图片为空,未保存。所以我尝试通过Component.onCompleted以另一种方式制作它,但它仍然不起作用。 (someSingleton.makeScreenshot()是一个调用QQuickWindow::grabWindow()的函数,就像上面的代码一样)。使其工作的唯一方法是在窗口完全加载时在MouseArea .onClicked中调用此函数。所以我得出结论,在2次首次尝试中QML树没有完全加载。

我也试过这段代码:

connect(rootObject,&QQuickWindow::afterRendering,[=] () {
    QImage image = rootObject->grabWindow();
    image.save("window.png","PNG",90);
});

但是程序的执行只是挂在第一行。

所以我的问题 - 当QML文档完全加载时,是否有一些事件触发?

P.S。在真正的应用程序中,我无法修改QML源代码,因此所有功能都必须在C ++部分。此处Component.onCompletedMouseArea .onClicked仅用于测试目的

2 个答案:

答案 0 :(得分:3)

好的,经过长时间的搜索,我找到了解决方案。像往常一样,我只需要更仔细地阅读Qt文档。

QImage QQuickWindow::​grabWindow()

http://doc.qt.io/qt-5/qquickwindow.html#grabWindow

警告: 此功能只能从GUI thread调用。

void QQuickWindow::​afterRendering()

http://doc.qt.io/qt-5/qquickwindow.html#afterRendering

警告: 此信号从scene graph rendering thread发出。

因此,插槽在场景图渲染线程中执行并因冲突而挂起。我刚刚更改了上面的示例,以确保插槽在GUI线程中执行,如here所述。

connect(rootObject,&QQuickWindow::afterRendering,this,[=] () {
    QImage image = rootObject->grabWindow();
    image.save("window.png","PNG",90);
},Qt::QueuedConnection);

答案 1 :(得分:1)

我不确定以下为什么不起作用:

#include <QtQuick>
#include <QtGui>

class Object : public QObject
{
    Q_OBJECT
public slots:
    void save() {
        QQuickWindow *window = qobject_cast<QQuickWindow*>(sender());
        QImage image = window->grabWindow();
        image.save("window.png", "PNG", 90);
    }
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    QByteArray data = "import QtQuick 2.3\n"
        "import QtQuick.Window 2.2\n"
        "Window {\n"
            "visible: true\n"
            "width: 360\n"
            "height: 360\n"
            "Text {\n"
                "anchors.centerIn: parent\n"
                "text: \"Hello, world!\"\n"
            "}\n"
            "MouseArea {\n"
                 "anchors.fill: parent\n"
            "}\n"
        "}";
    engine.loadData(data);

    QQuickWindow *rootObject = qobject_cast<QQuickWindow *>(engine.rootObjects().first());

    Object object;
    QObject::connect(rootObject, SIGNAL(afterRendering()), &object, SLOT(save()));

    return app.exec();
}

#include "main.moc"

可能是使用不正确,或者实际上某处存在错误。我不确定。如果您不确定,请在邮件列表中查询,或创建错误报告。

但是,如果您使用frameSwapped(),则可以使用:

    QObject::connect(rootObject, SIGNAL(frameSwapped()), &object, SLOT(save()));