web-dev-qa-db-ja.com

Qt / QML:QImageをC ++からQMLに送信し、GUIでQImageを表示する

Publisherオブジェクトを定期的に発行するクラスQImageを作成しました。

しかし、QImageをQML要素に描画するのは大変です。 ImageおよびCanvas QMLコンポーネントはQUrlの代わりにQImageを必要とするようですが、QImageからQUrlへ。 Edit4:QUrlと言っても、画像をURLに変換しようとしているわけではありません。それはナンセンスです。つまり、ディスク上にないこのイメージへの参照を生成したいということです。QMLコンポーネントが要求しているデータ型はURLです。

いくつかの調査を行ったところ、QQuickImageProviderが解決策を提供していることがわかりましたが、QImage信号をQUrlに変換する方法を説明したドキュメントは見つかりませんでした描画に使用します。サンプルコードまたはリファレンスドキュメントをいただければ幸いです。

ご協力いただきありがとうございます!

編集1:

私はここを見てきました: http://qt-project.org/doc/qt-5.0/qtquick/qquickimageprovider.html QImageをクイック画像に渡す方法がわかりませんプロバイダーとそれからQUrlを作成します。

編集2。これがヘッダーです。実装は重要ではありません。

class Publisher
{
    Q_OBJECT

public:
    Publisher(QObject* parent = 0);

    virtual ~Publisher(void);

Q_SIGNALS:

    void newImage(const QImage& newImage);
};

編集3。ここに私のQMLコードがありますが、QImageを描画する方法がわかりませんので、このコードは無意味です。

私のmain.cppファイル

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

    qmlRegisterType<Publisher>("Components", 1, 0, "Publisher");

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/QQuickViewExample/main.qml"));
    viewer.showExpanded();

    return app.exec();
}

main.qmlファイル

import QtQuick 2.0
import Components 1.0

Rectangle {
    id : testRect
    width: 360
    height: 360

    Image{
        anchors.fill: parent
        id: myImage

        Publisher {
            id: myPub

            onNewImage: {
                myImage.source = newImage;  #I know this doesnt work, it needs a QUrl and not a QImage
            }
        }
    }
}
28
trianta2

言い換えると、QImageを運ぶ信号を発するクラスがあり、そのイメージでQMLのアイテムを更新したいのですか?さまざまなソリューションがありますが、いずれも「QImageからQUrlへの変換」を含みません(つまり、画像データを保持するdata URLを取得する必要はありません...)

画像プロバイダーを使用する

これは、QMLファイルでプレーンImageアイテムを使用できることを意味します。

  1. QQuickImageProviderサブクラスを作成します。 QImageメンバー(プロバイダーへの画像)を提供し、requestImageをオーバーライドしてその画像を提供します(実際に要求されるidは重要ではありません。以下を参照)。 QImageを受け取り、メンバーを更新します。
  2. Publisher信号をプロバイダーのスロットに接続します
  3. _QQmlEngine::addImageProvider_を介してプロバイダーをQMLエンジンにインストールします(_QQuickView::engine_を参照)。再びidは実際には問題ではなく、賢明なものを使用してください
  4. QMLでは、このようなソースで単純なImage要素を使用します

    _Image {
        id: myImage
        source: "image://providerIdPassedToAddImageProvider/foobar"
    }
    _

    foobarがプロバイダーに渡されますが、これも重要ではありません。

  5. 私たちはもうすぐそこにいます。今では、QMLワールドのイメージ更新をPushだけで行う必要があります(そうでなければ、Imageはいつそれ自体を更新するかを知ることはありません)。 Connections要素と少しのJSを使用してこれを行う方法については、 私の答えはこちら を参照してください。

    一般に、PublisherをQMLタイプにする必要はなく、C++でoneインスタンスを作成し、それを介してQMLワールドに公開するだけです。 _QQmlContext::setContextProperty_。

カスタムQt Quick 2アイテムを使用する

QQuickPaintedItemは、Paintを取るQPainterメソッドを提供するため、おそらくジョブにとって最も便利です。したがって、大きな計画は

  1. サブクラスQQuickPaintedItem:サブクラスは、ペイントされるQImageを格納し、新しいQImageを設定するスロットを持っています。また、そのPaint実装は、_QPainter::drawImage_を使用して画像を単純にペイントします。
  2. qmlRegisterTypeを介してQMLワールドにサブクラスを公開します(QMLで使用できるように)
  3. 新しい画像を運ぶ信号をアイテムのスロットに接続する方法を見つけてください。

    これは難しい部分かもしれません。

    C++で接続を実行するには、アイテムが作成されたことを把握する(およびそのポインターを取得する)方法が必要です。通常、これはobjectNameプロパティを何らかの値に割り当て、ルートオブジェクト(QQuickView::rootObject()によって返される)でfindChildを使用して、アイテム自体。その後、通常どおりconnectを使用できます。

    Or、代わりにQMLで公開されたパブリッシャーC++オブジェクトのConnections要素を介して、上記のようにQMLで接続を実行できます。

    _MyItem {
        id: myItem
    }        
    
    Connections {
        target: thePublisherObjectExposedFromC++
        onNewImage: myItem.setImage(image)
    }
    _

    これには、MyItemインスタンスをいつ作成しても動作するという利点があります。 QMLでQImageタイプを処理できるかどうかわからないので、100%確実に機能するかどうかはわかりません。

37
peppe

QMLに埋め込みたい画像生成C++クラスがあったときは、C++クラスをQDeclarativeItemのサブクラスにすることで常にそれを行いました(新しいQtQuick 2.0に相当するものがありますもちろん)、適切な描画コードでPaintメソッドをオーバーライドします。

void MyItem::Paint(QPainter* Painter,const QStyleOptionGraphicsItem*,QWidget*) {
  Painter->drawImage(QPointF(0.0f,0.0f),_image);
}

適切なサイズのQImageが既にある場合...およびJob Done。アニメーションの場合、描画する新しいものがあるときにupdate()にpingを実行します。

3
timday