【问题标题】:Display and refresh an image in QML在 QML 中显示和刷新图像
【发布时间】:2016-08-13 02:34:21
【问题描述】:

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

我的程序目前正在使用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 

【问题讨论】:

    标签: c++ qt qml


    【解决方案1】:

    很简单,只需要在paint()方法中绘制图片即可:

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

    然后每次yourImage 更改时调用update()

    不要绘制原始数据,使用正确的格式创建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 对象时。相反,您应该使用带有排队连接的信号和插槽,通过该连接传递图像,然后设置图像并从StreamPainter 的插槽调用update()

    你不需要那个:

    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);
    

    【讨论】:

    • 谢谢,我会试试的。但是在 QML 部分我如何显示它?我必须在那里使用 update 或 Rendertarget 吗?
    • 只创建一个对象的实例。看看这个答案,它比你的问题复杂一点,但它涵盖了你需要的一切:stackoverflow.com/questions/35460369/…
    • @Dinendal - 您当前的项目大小为 0x0...给它一些宽度和高度。
    • 是的,我的属性名称无效。我必须为每个人声明一个 Q_Property 吗?
    • 你继承QQuickPaintedItem吗?它声明了这些属性。
    【解决方案2】:

    在我的例子中,我使用组件内的函数刷新 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()
    

    【讨论】:

      猜你喜欢
      • 2018-01-28
      • 2013-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多