将 QML 项目作为图像复制到剪贴板C++

Copy QML Item to Clipboard as Image thru C++

本文关键字:复制 剪贴板 C++ 图像 QML 项目      更新时间:2023-10-16

我一直在尝试使用QML Charts API,并决定将ChartView作为图像导出到剪贴板。我在网上冲浪发现了一个有效的解决方案,其中人们通过Javascript抓取该项目作为图像并将QVariant数据发送给C++。这很好并且有效,但我想知道是否不可能只发送一个 QQuickItem* 或像这样轻的东西,然后在C++做抓取和任何东西,正如每个人都说的那样尽可能避免 Javascript,抓取图像似乎是一项繁重的操作。

这是我现在使用的工作代码。

图表导出器.h


    #ifndef CHARTEXPORTER_H
    #define CHARTEXPORTER_H
    #include 
    #include 
    class QQuickItem;
    class ChartExporter : public QObject
    {
        Q_OBJECT
    public:
        explicit ChartExporter(QObject *parent = 0);
        Q_INVOKABLE void copyToClipboard(QVariant data);
    };
    #endif // CHARTEXPORTER_H

图表导出器.cpp


    includes....
    ChartExporter::ChartExporter(QObject *parent) : QObject(parent)
    {
    }
    void ChartExporter::copyToClipboard(QVariant data){
        QImage img = qvariant_cast(data);
        QApplication::clipboard()->setImage(img,QClipboard::Clipboard);
    }

主.qml


    import QtQuick 2.7
    import QtQuick.Controls 2.0
    import QtQuick.Layouts 1.0
    import QtCharts 2.0
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello Chart World")
        ColumnLayout{
            spacing: 2
            anchors.fill: parent
            ChartView{
                id: chart
                title: "Testing Charts"
                anchors.fill: parent
                legend.alignment: Qt.AlignTop
                antialiasing: true
                animationOptions: ChartView.AllAnimations
                PieSeries {
                    id: pieSeries
                    PieSlice { label: "Volkswagen"; value: 13.5; exploded: true}
                    PieSlice { label: "Toyota"; value: 10.9 }
                    PieSlice { label: "Ford"; value: 8.6 }
                    PieSlice { label: "Skoda"; value: 8.2 }
                    PieSlice { label: "Volvo"; value: 6.8 }
                }
            }
            Button{
                Layout.alignment: Qt.AlignBottom
                text: qsTr("Copy to Clipboard")
                onClicked: {
                    var stat = chart.grabToImage(function(result) {
                                            Printer.copyToClipboard(result.image);
                                        });
                }
            }
        }
    }

主.cpp


    includes ....
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QApplication app(argc, argv);
        ChartExporter printer;
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("Printer", &printer);
        engine.load(QUrl(QLatin1String("qrc:/main.qml")));
        return app.exec();
    }

你们有没有关于如何通过简单地调用一个方法将所需的项目发送到C++的想法,如下所述并处理其中的所有内容?


    Button{
                Layout.alignment: Qt.AlignBottom
                text: qsTr("Copy to Clipboard")
                onClicked: {
                      Printer.copyToClipboard(chart);
                }
            }

我找到了一种方法来做到这一点C++!

当我在onClicked处理程序(Javascript)中执行Printer.copyToClipboard(chart)时,我实际上是在向C++层发送QObject*。在我的C++方法中,我可以做一个qobject_cast并将其作为图像抓取。必须考虑到抓取操作是异步的。因此,我需要将副本复制到插槽内的剪贴板,该插槽在抓取完成后被调用。

所以,以下是我得到的方式。如果有人有更好的方法,很高兴知道。

图表导出器.h


    #ifndef CHARTEXPORTER_H
    #define CHARTEXPORTER_H
    #include <QObject>
    #include <QVariant>
    #include <QSharedPointer>
    class QQuickItem;
    class QQuickItemGrabResult;
    class ChartExporter : public QObject
    {
        Q_OBJECT
    private:
        QSharedPointer p_grabbedImage;
    protected slots:
        void doCopy();
    public:
        explicit ChartExporter(QObject *parent = 0);
        Q_INVOKABLE void copyToClipboard(QObject *item);
    };
    #endif // CHARTEXPORTER_H

图表导出器.cpp


    #include <QDebug>
    #include <QImage>
    #include <QQuickItem>
    #include <QClipboard>
    #include <QApplication>
    #include <QSharedPointer>
    #include <QQuickItemGrabResult>
    #include "chartexporter.h"
    ChartExporter::ChartExporter(QObject *parent) : QObject(parent), p_grabbedImage(nullptr)
    {
    }
    void ChartExporter::copyToClipboard(QObject* item){
        if(item){
            auto itm = qobject_cast(item);
            p_grabbedImage = itm->grabToImage(QSize(itm->width()*2,itm->height()*2));
            connect(p_grabbedImage.data(), &QQuickItemGrabResult::ready, this, &ChartExporter::doCopy);
        }
    }
    void ChartExporter::doCopy(){
        if(p_grabbedImage.data()){
            auto img = p_grabbedImage->image();
            QApplication::clipboard()->setImage(img, QClipboard::Clipboard);
        }
        disconnect(p_grabbedImage.data(),&QQuickItemGrabResult::ready, this, &ChartExporter::doCopy);
    }

主.qml


    import QtQuick 2.7
    import QtQuick.Controls 2.0
    import QtQuick.Layouts 1.0
    import QtCharts 2.0
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello Chart World")
        ColumnLayout{
            spacing: 2
            anchors.fill: parent
            ChartView{
                id: chart
                title: "Testing Charts"
                anchors.fill: parent
                legend.alignment: Qt.AlignTop
                antialiasing: true
                animationOptions: ChartView.AllAnimations
                PieSeries {
                    id: pieSeries
                    PieSlice { label: "Volkswagen"; value: 13.5; exploded: true}
                    PieSlice { label: "Toyota"; value: 10.9 }
                    PieSlice { label: "Ford"; value: 8.6 }
                    PieSlice { label: "Skoda"; value: 8.2 }
                    PieSlice { label: "Volvo"; value: 6.8 }
                }
            }
            Button{
                Layout.alignment: Qt.AlignBottom
                text: qsTr("Copy to Clipboard")
                onClicked: {
                    Printer.copyToClipboard(chart);
                }
            }
        }
    }

主.cpp


    #include <QApplication>
    #include <QQmlContext>
    #include <QQmlApplicationEngine>
    #include "chartexporter.h"
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QApplication app(argc, argv);
        ChartExporter printer;
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("Printer", &printer);
        engine.load(QUrl(QLatin1String("qrc:/main.qml")));
        return app.exec();
    }