我现在正在使用一个应用程序加载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.onCompleted
和MouseArea .onClicked
仅用于测试目的。
答案 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()));