QQuickWindow::grabWindow: 场景图已经在使用

Posted

技术标签:

【中文标题】QQuickWindow::grabWindow: 场景图已经在使用【英文标题】:QQuickWindow::grabWindow: scene graph already in use 【发布时间】:2015-10-16 08:24:39 【问题描述】:

我尝试了这里显示的代码:How to take ScreenShot Qt/QML

在执行时,我收到标题中写的错误。

我的 main.cpp 是:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QImage>
#include <QDebug>
#include "screenshot.h"
#include <QQuickView>
#include <QQmlContext>

int main(int argc, char *argv[])

    QGuiApplication app(argc, argv);

    const char* drigUi = "DrigUI"; 
    qmlRegisterType <screenCapture> (drigUi, 1, 0, "ScreenShot");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();

我使用了这个捕获功能:

void screenCapture::capture(QString const &path) const

    QImage img = currentView_->grabWindow();
    img.save(path);

并在构造函数中添加以下内容:

currentView_ = new QQuickView;

我的main.qml

import QtQuick 2.4
import QtQuick.Window 2.2

import DrigUI 1.0

Window

    visible: true
    height: 370
    width: 370

    ScreenShot  id: screenShot 

    Rectangle
    
        id: ll
        height: 30
        width: 50
        x: 180; y: 0; color: "red"
        MouseArea
        
            anchors.fill: parent
            onClicked: screenShot.capture ("l.png")
        
    

这个错误是什么意思?有什么方法可以解决?我还可以在这里提供什么信息?

【问题讨论】:

你可以提供你的 main.qml。最小化为 SSCCE,重现该问题。 @SaZ 我特意没有提供。它不包含任何非常重要的东西。现在,我会照你说的在这里。 @SaZ 完成。什么是 SSCCE? 我不确定,但请尝试对您的 screenCapture::capture 方法进行断言:Q_ASSERT( QThread::currentThread() == qApp-&gt;thread() );。文档中有一些 cmets:doc.qt.io/qt-5/qquickwindow.html#grabWindow @SaZ 如何在捕获方法中获取 qApp 对象。该对象在 main.cpp 中。不是吗? 【参考方案1】:

我在QtCenter.org too, and got the enlightenment from there.上发布了这个问题

我问你为什么要创建一个空 QQuickView 的屏幕截图? 您不想截取您在 QML 中创建的 Window 的屏幕截图吗?

我意识到我没有在main.cpp 的任何地方使用QQuickView。所以这意味着我使用的 QQuickView 是空的。

我的程序的另一部分是使用QQuickWindow而不是QQuickView,所以我将QQuickView替换为QQuickWindow如下:

ScreenCapture.h

#ifndef SCREENSHOT_H
#define SCREENSHOT_H

#include <QObject>

class QString;
class QQuickWindow;

class screenCapture : public QObject

    Q_OBJECT
public:
    explicit screenCapture (QQuickWindow *parent = 0);

public slots:
    void capture (QString const &path) const;

private:
    QQuickWindow *currentWindow;
;

#endif // SCREENSHOT_H

ScreenCapture.cpp

#include <QPixmap>
#include <QQuickView>
#include <QDebug>
#include "screenshot.h"

screenCapture::screenCapture(QQuickWindow *currentWindow) :
    QObject(0), currentWindow (currentWindow)



void screenCapture::capture (QString const &path) const

    QImage p = currentWindow->grabWindow ();
    bool kk = p.save (path);
    qDebug () << kk;

ma​​in.cpp

int main(int argc, char *argv[])

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    QObject      *topLevel = engine.rootObjects().value(0);
    QQuickWindow *window   = qobject_cast<QQuickWindow *>(topLevel);

    screenCapture launcher (window);

    engine.rootContext()->setContextProperty("ScreenShot", &launcher);

    window->show();

    return app.exec();

现在,在QML端,我们可以直接使用

ScreenShot.capture ("/home/*****/Desktop/l.png")

我们想要的任何地方。它有效。

【讨论】:

以上是关于QQuickWindow::grabWindow: 场景图已经在使用的主要内容,如果未能解决你的问题,请参考以下文章