在QML

时间:2016-04-20 12:11:12

标签: c++ qt qml

我不明白如何使用QQuickPaintedItem类(或者其他方法?)在QML中显示图像。

我的程序当前正在使用QImage和一个ImageProvider显示它,它可以正常工作但随机崩溃,所以我想尝试另一种方法。

此外,每次传输新帧时都应刷新图像。

我从uchar原始数据中获取信息,但我不知道如何从原始数据中绘制。

此外,新的原始数据大约为60 fps,因此QML需要以此速率刷新图像。

编辑:

代码的其他部分:

我的课程是:

class StreamPainter : public QQuickPaintedItem
{
    Q_OBJECT

public:
    StreamPainter(QQuickItem *p = 0):QQuickPaintedItem(p){}
    ~StreamPainter();

    void paint(QPainter *painter){painter->drawImage(QPoint(0, 0), _streamImage);}


public slots:
    void onImageAvailable(QImage image) {
        _streamImage = image;
        update();
private:
    QImage _streamImage;

};

主要:

对于无效的属性名称,这是由于导入StreamPainter 1.0,似乎它不喜欢这个名称,因为它被灌输了,我已经将它改为myModule并且错误消失了。

qmlRegisterType<StreamPainter>("myModule", 1, 0, "StreamPainter");

创建对象和线程:

streamImage = new StreamPainter();
myPipeThread = new PipeThread(streamImage);

线程构造函数:

PipeThread::PipeThread(StreamPainter* spvideostr)
:QThread(),
 _namedPipe(INVALID_HANDLE_VALUE),
 _spvideostr(spvideostr),
 _abort(false),
 _rawData(NULL)
{
    ...
}

线程类,我已添加:

signals:
    void imageAvailable(QImage image);

然后在我的线程中,我进行连接,并在此期间创建QImage并发出信号:

connect(this, SIGNAL(imageAvailable(QImage)), _spvideostr, SLOT(onImageAvailable(QImage)));

while(...)
    QImage clImage(_rawData, IMG_WIDTH, IMG_HEIGHT,     QImage::Format_Indexed8);
    emit imageAvailable(clImage);

QML:

import QtQuick 2.0

import MyModule 1.0

StreamPainter {

    width : 100 
    height : 100 

2 个答案:

答案 0 :(得分:0)

这很简单,你要做的就是用paint()方法绘制图像:

void paint(QPainter *painter) {
    painter->drawImage(QPoint(0, 0), yourImage);
}

每次update()更改时都会致电yourImage

不要绘制原始数据,用适当的格式从中创建QImage并绘制它。您可以使用静态方法QImage fromData(const uchar *data, int size, const char *format = Q_NULLPTR)。由于QImage是隐式共享对象,因此每次获得新数据时都可以有效yourImage = QImage::fromData(...),然后update()

编辑:

您应该在QML中创建对象。另外,看看如何使用线程,请记住UI元素只能从主线程访问。这意味着您无法执行此操作:

_spvideostr->setStreamImage(clImage);
_spvideostr->update();

当您从另一个线程访问UI对象时。相反,您应该使用带有排队连接的信号和插槽,通过该连接传递图像,然后设置图像并从update()的插槽中调用StreamPainter

你不需要:

Q_PROPERTY(QImage streamImage READ streamImage WRITE setStreamImage NOTIFY streamImageChanged)

此图片只能从该课程中访问。所以你不需要那些:

QImage streamImage();
void setStreamImage(QImage clImage);

signals:
    void streamImageChanged(QImage Image);

你需要的是:

public slots:
    void onImageAvaiable(QImage image) { ...set image and call update }

PipeThread中,您需要一个信号void imageAvaiable(QImage),将imageAvaiable连接到onImageAvaiable并发出图片:

QImage clImage(_rawData, IMG_WIDTH, IMG_HEIGHT, QImage::Format_Indexed8);
emit imageAvaiable(clImage);

答案 1 :(得分:0)

在我的例子中,我使用组件内部的函数刷新QML中的图像,如下所示:

Image {
                id: imageLogo
                cache: false
                anchors.fill: parent
                //anchors.leftMargin: 20
                Layout.preferredWidth: Math.round(parent.width / 1.5)
                Layout.preferredHeight: Math.round(parent.height * 2)

                function reloadImage() {
                    var oldSource = source
                    source = ""
                    source = oldSource
                }//function to refresh the source

            }

然后我只在你想重新加载图像的地方调用这个函数

imageLogo.reloadImage()