QML:文档完全加载时触发的事件
QML: Event which triggers when document was completly loaded
我现在在开发一个应用程序 加载 QML 文件并制作 window 的屏幕截图。
这就是现在的样子:
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()
的函数)。让它工作的唯一方法是在 window 完全加载时在 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
这里只是为了测试目的.
我不确定为什么以下内容不起作用:
#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()));
好的,经过长时间的搜索,我发现 solution.As 通常我只需要更仔细地阅读 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
.
发出
所以,slot是在场景图渲染线程中执行的,由于冲突挂掉了。我刚刚更改了上面的示例,以确保插槽按照 here.
所述在 GUI 线程中执行
connect(rootObject,&QQuickWindow::afterRendering,this,[=] () {
QImage image = rootObject->grabWindow();
image.save("window.png","PNG",90);
},Qt::QueuedConnection);
我现在在开发一个应用程序 加载 QML 文件并制作 window 的屏幕截图。 这就是现在的样子:
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()
的函数)。让它工作的唯一方法是在 window 完全加载时在 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
这里只是为了测试目的.
我不确定为什么以下内容不起作用:
#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()));
好的,经过长时间的搜索,我发现 solution.As 通常我只需要更仔细地阅读 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
.
所以,slot是在场景图渲染线程中执行的,由于冲突挂掉了。我刚刚更改了上面的示例,以确保插槽按照 here.
所述在 GUI 线程中执行connect(rootObject,&QQuickWindow::afterRendering,this,[=] () {
QImage image = rootObject->grabWindow();
image.save("window.png","PNG",90);
},Qt::QueuedConnection);