Как отобразить QPixmap в Qt Quick Image?

Я работаю над небольшим приложением Qt Quick с QML и C++ для создания скриншотов. Функция grabWindow() возвращает QPixmap. Я хотел бы отобразить этот скриншот в Qt Quick Image, но Image принимает только URL-адреса. Как мне отобразить мой QPixmap без необходимости сначала сохранять его по пути?

Мой скриншот.cpp:

#include <QtQuick>
#include "screenshot.h"

Screenshot::Screenshot() {}

QPixmap *Screenshot::grabScreen() {
  QScreen *screen = QGuiApplication::primaryScreen();
  if(screen)
    *originalPixmap = screen->grabWindow(0);
  return originalPixmap;
}

скриншот.h:

#ifndef SCREENSHOT_H
#define SCREENSHOT_H

#include <QObject>
class QString;
class QQuickView;

class Screenshot : public QObject
{
  Q_OBJECT
  public:
    Screenshot();
    Q_INVOKABLE QPixmap *grabScreen();
  public slots:
  private:
    QPixmap *originalPixmap;
};

#endif // SCREENSHOT_H

основной.qml:

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.4
import com.pixmate.screenshot 1.0

ApplicationWindow {
    visible: true
    width: 420
    height: 380
    menuBar: MenuBar {
        Menu {
            title: "Screen"
            MenuItem {
                text: "New Screenshot"
                shortcut: "Ctrl+Shift+3"
            }
            MenuItem {
                text: "Save Screenshot"
                shortcut: "Ctrl+Shift+4"
            }
        }

        Menu {
            title: "Edit"
            MenuItem { text: "Cut" }
            MenuItem { text: "Copy" }
            MenuItem { text: "Paste" }
        }
    }

    Screenshot {
        id: screenShot
    }

    Image {
        id: screenshotImage
        visible: true
        anchors.horizontalCenter: parent.horizontalCenter
        y: 10
        width: 240
        height: 160
        source: "<insert URL here>"
    }

    GroupBox {
        title: "Options"
        y: 180
        x: 10
        width: parent.width-20
        Column {
            spacing: 10
            Label {
                text: "Screenshot Delay"
            }
            SpinBox {
                maximumValue: 120
                value: 3
                suffix: " s"
                width: 80
                onValueChanged: {
                    if(value == 0) {
                        hideThisWindowCheckbox.enabled = false;
                        hideThisWindowCheckbox.checked = false;
                    } else {
                        hideThisWindowCheckbox.enabled = true;
                    }
                }
            }
            CheckBox {
                id: hideThisWindowCheckbox
                text: "Hide this window"
                checked: true
                /*style : CheckBoxStyle {
                    padding.top: 10
                }*/
            }
        }
        Column {
            x: 185
            spacing: 10
            RadioButton {
                id: captureScreenRadioButton
                text: "Capture entire screen"
                checked: true
                onClicked: {
                    captureActiveWindowRadioButton.checked = false
                    captureScreenSelectionRadioButton.checked = false
                }
            }
            RadioButton {
                id: captureActiveWindowRadioButton
                text: "Capture active window"
                enabled: false // disabled for now
                onClicked: {
                    captureScreenRadioButton.checked = false
                    captureScreenSelectionRadioButton.checked = false
                }
            }
            RadioButton {
                id: captureScreenSelectionRadioButton
                text: "Capture selected area"
                enabled: false // disabled for now
                onClicked: {
                    captureScreenRadioButton.checked = false
                    captureActiveWindowRadioButton.checked = false
                }
            }
        }
    }
    Button {
        id: newScreenshotButton
        text: "New Screenshot"
        y: 320
        x: 10
        onClicked: {
            screenshotImage.data = screenShot.grabScreen();
        }
    }

    Button {
        id: saveScreenshotButton
        text: "Save Screenshot"
        y: 320
        x: 165
    }
    Button {
        id: quitButton
        text: "Quit"
        y: 320
        x: 320
    }
}

main.cpp

#include <QGuiApplication>
#include <QQmlContext>
#include <QQuickView>
#include <QQmlApplicationEngine>
#include "src/screenshot.h"

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

    qmlRegisterType<Screenshot>("com.pixmate.screenshot", 1, 0, "Screenshot");

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

    return app.exec();
}

редактировать: когда я запускаю его, как сейчас, я получаю

qrc:/main.qml:126: Ошибка: Неизвестный тип возвращаемого значения метода: QPixmap*

Заранее спасибо!


person calmandniceperson    schedule 04.01.2016    source источник
comment
Взгляните на QQuickImageProvider. Этот хороший ответ должен помочь в его использовании.   -  person BaCaRoZzo    schedule 04.01.2016
comment
@BaCaRoZzo Спасибо за ответ! Посмотрел ваши ссылки и ничего не понял. Могу ли я просто использовать graphWindow() в функции requestPixmap() и возвращать ее?   -  person calmandniceperson    schedule 04.01.2016
comment
@BaCaRoZzo Я понял это, и теперь это работает. Я только что вызвал свою функцию захвата окна() из requestPixmap. Большое тебе спасибо :)   -  person calmandniceperson    schedule 04.01.2016
comment
Очень хороший. :) Пожалуйста, дайте точный ответ на свой вопрос и не забудьте проголосовать за ответ Саймона, если он вам помог. Спасибо.   -  person BaCaRoZzo    schedule 04.01.2016
comment
@BaCaRoZzo Извините, что снова вас беспокою. Есть ли способ изменить функцию requestPixmap? Я хочу установить задержку и передать ее в качестве аргумента.   -  person calmandniceperson    schedule 04.01.2016
comment
Какой сценарий использования? Поставщик изображений просто предоставляет изображение в QML, вы можете добавить задержку в QML через файл Timer. Добавлять задержку внутри провайдера мне не имеет смысла.   -  person BaCaRoZzo    schedule 04.01.2016
comment
@BaCaRoZzo Я хочу, чтобы SpinBox устанавливал задержку, которая будет задерживать создание снимка экрана для заданного значения. До сих пор я использовал QtWidgets и C++ и использовал singleShot QTimer для вызова SLOT через некоторое время, но здесь это не сработает. Я бы даже не знал, что передать в качестве объекта-приемника   -  person calmandniceperson    schedule 04.01.2016
comment
@ddriver, я должен был опубликовать и твой ответ. Это очень информативно и имеет полезный код. Спасибо, что поделились.   -  person BaCaRoZzo    schedule 04.01.2016