我有一个QQuickWidget,并想使用QQuickWindow::grabWindow()截取屏幕截图。但是,当我这样做时,QQuickWindow变成图像并且没有响应。
以下是最小的可复制代码:
该错误可在Qt5.13到Qt5.15.1的 Release模式下重现(由于某些原因,Qt在调试中抛出了断言)
//TestWidget.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets quickwidgets

CONFIG += c++11

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h \
    windowgrabber.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

DISTFILES += \
    Main.qml

RESOURCES += \
    qml.qrc
//main.cpp
#include <QApplication>
#include <QQuickWidget>
#include <QQmlContext>
#include "windowgrabber.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QQuickWidget *quickWidget = new QQuickWidget;
    quickWidget->rootContext()->setContextProperty("windowGrabber", new WindowGrabber(quickWidget));
    quickWidget->setSource(QUrl("qrc:/Main.qml"));
    quickWidget->show();

    return a.exec();
}

//Main.qml
import QtQuick 2.0
import QtQuick.Controls 2.0

Page {
    Button {
        id: button
        text: "grab window"
        onClicked: windowGrabber.grabWindow(button)
    }
}
//WindowGrabber.h
#ifndef WINDOWGRABBER_H
#define WINDOWGRABBER_H

#include <QObject>
#include <QQuickItem>
#include <QQuickWindow>

class WindowGrabber : public QObject
{
    Q_OBJECT
public:
    WindowGrabber(QObject *parent = nullptr) : QObject(parent) {}
    Q_INVOKABLE static void grabWindow(QQuickItem *item) {
        item->window()->grabWindow();
    }
};

#endif // WINDOWGRABBER_H
该代码创建一个QQuickWidget,其源设置为Main.qml。单击qml内的按钮时,我想截屏。但是在单击按钮后,快速小部件内的QQuickWindow变为图像,并且按钮也变为图像。我已经使用QWidget::createWindowContainer进行了测试,并且可以工作,但是最好的解决方案是使用QQuickWidget。任何人都知道为什么会发生这种情况吗?

最佳答案

QQuickWidget使用一个不可见的QQuickWindow渲染项目,并且该渲染又在QWidget中渲染,因此,当尝试保存图像时,它会产生干扰,导致滞后,正如我在this post中已经指出的那样。
一个可能的解决方案是直接从QQuickWidget中获取:

#ifndef WINDOWGRABBER_H
#define WINDOWGRABBER_H

#include <QObject>
#include <QQuickWidget>

class WindowGrabber : public QObject
{
    Q_OBJECT
public:
    WindowGrabber(QQuickWidget *widget): m_widget(widget)  {}
    Q_INVOKABLE void grabWindow() {
        if(m_widget){
            QPixmap img = m_widget->grab();
            qDebug() << img;
        }
    }
private:
    QPointer<QQuickWidget> m_widget;
};


#endif // WINDOWGRABBER_H
#include <QApplication>
#include <QQuickWidget>
#include <QQmlContext>
#include "windowgrabber.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QQuickWidget quickWidget;
    WindowGrabber grabber(&quickWidget);
    quickWidget.rootContext()->setContextProperty("windowGrabber", &grabber);
    quickWidget.setSource(QUrl("qrc:/main.qml"));
    quickWidget.show();

    return a.exec();
}
Button {
    id: button
    text: "grab window"
    onClicked: windowGrabber.grabWindow()
}

09-06 15:17