QML实时更新图像组件,类似QLabel的作用

1、瞎叨叨

众所周知,QML在与OpenCV配合的时候常常让人很头大,因为其并没有原生支持像QLabel一样赋值式的类PictureBox组件,没法结合OpenCV采集实时更新画面。

同时,也没法和QtWidgets一样利用OpenCV的imshow的窗口句柄将它嵌入到QtWidgets程序中,因此要实现类似QLabel的功能就只能自己来实现了。

参考了很多大佬的方案,最终发现下面这位大佬的实现最牛逼,可跨线程的图片实时显示:

GitHub - 188080501/JQImageItem: 基于FBO显示QImage到QML中

可是后续在使用的时候,可能是我不太会用,完全基于QQuickFramebufferObject的实现我用着效果反而没有基于QQuickPaintedItem的好。(因为后者用着实在可以了就没去管前者的问题咋解决了)

后面在实际使用中发现作者大大基于QQuickPaintedItem的实现性能比QLabel还是要差上一截,还是决定看看怎么回事,就基于他的版本小改了一下,并就图片的缩放和摆放也修改了一下。

2、源码

// PaintItem.h
#pragma once
#ifndef PAINTITEM_H
#define PAINTITEM_H

#include <QQuickPaintedItem>
#include <QImage>
#include <QPainter>
#include <QQuickPaintedItem>
#include <QMutexLocker>


class PaintItem : public QQuickPaintedItem
{
    Q_OBJECT
        Q_DISABLE_COPY(PaintItem)
public:
    PaintItem();
    virtual ~PaintItem() = default;

public:
    void setImage(const QPixmap& img);

private:
    void paint(QPainter* painter) override;

private:
    QMutex mutex_;
    QPixmap buffer_;
};

#endif
// PaintItem.cpp
#include "PaintItem.h"

PaintItem::PaintItem()
{
    this->setRenderTarget(QQuickPaintedItem::FramebufferObject);
}

void PaintItem::setImage(const QPixmap& image)
{
    QMutexLocker locker(&mutex_);

    if (!image.isNull() && (image.size() != this->size().toSize()))
    {
        buffer_ = image.scaled(this->size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation);
    }
    else
    {
        buffer_ = image;
    }
    QMetaObject::invokeMethod(this, std::bind(&PaintItem::update, this, QRect()));
}

void PaintItem::paint(QPainter* painter)
{
    QMutexLocker locker(&mutex_);
    QRect rectDevice = QRect(0, 0, this->width(), this->height());
    if (buffer_.isNull())
    {
        painter->setBrush(QColor(0, 0, 0));
        painter->drawRect(rectDevice);
    }
    else
    {
        QRect rectImg(buffer_.rect());
        rectImg.moveCenter(rectDevice.center());
        painter->drawPixmap(rectImg.topLeft(), buffer_);
    }
}


3、原大佬的MIT许可

再附上作者大大的MIT许可证,别人开源了我可不能侵权不是?

Copyright Jason and others

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 4、用法

  • 在程序C++中注册该类型
qmlRegisterType<PaintItem>("PaintItemModule", 1, 0, "PaintItem");
  • 在程序qml文件中导入 
import PaintItemModule 1.0
  • 在qml中实例化一个对象
Window {
    PaintItem{
        id: imageItem
        anchors.fill: parent
        visible: true
    }
}
  •  通过一定的方法将这个对象地址传回C++中,我是在qml中新建了一个C++类camera,调用其SetImgItem函数将其回去的。
camera.SetImgItem(imageItem);
  • C++中的SetImgItem函数很简单:
void Camera::SetImgItem(PaintItem* item)
{
	m_item = item;
}
  • 然后要更新画面的时候就在C++的camera类中利用setImage函数对其赋值即可:
this->m_item->setImage(QPixmap::fromImage(QImage(img.data, img.cols, img.rows, img.step, QImage::Format_RGB888)));

 PS

我这里弄了默认是保持图片比例,缩放到控件的最大矩形,并且图片居中显示。要是有别的需求,可以修改PaintItem.cpp中的“Qt::KeepAspectRatio”改变图片缩放。修改paint函数中drawPixmap的传入参数来改变图片的放置位置。

  • 39
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值