QML学习笔记——图片动态显示(Image与QQuickImageProvider)

原文地址::https://blog.csdn.net/qq_22049783/article/details/81091766

相关文章

1、QML之图片动态显示(Image与QQuickImageProvider)----https://blog.csdn.net/caoshangpa/article/details/83959611

 

写在前面
项目中需要一个预览和回显的功能,需要通过udp接收图片数据,并在界面上动态显示,在网上研究一番后,最终选择了Image和QQuickImageProvider来实现。
这里只是记录下关键机制,实际应用场景更复杂,需要拆包并包,考虑超时,掉线,多设备同时预览的效率等问题。
实际使用


环境
Qt 5.9.3 + MinGW
window 10
Image
Image来实现图片的显示,可以显示本地图片和网络图片。
Image {
    id: img_preview;
    width: 170;
    height: 100;
    source: "qrc:/bord/img/block.jpg"; //加载资源文件
    //source: "file:///E:/bord/img/block.jpg"; //加载本地图片
    //cache:false;  //是否缓存 
}
1
2
3
4
5
6
7
8
QQuickImageProvider
The QQuickImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML.
可以将QPixmap或者QImage的图片提供给QML进行显示。
具体实现
新建UDP监听线程
建立一个UDP线程单独监听图片数据,这里写的比较简单,假设udp直接发的一包完整jpg图片数据,data_image 为全局变量。mutex_prest为互斥锁(QMutex),因为data_image会被其他线程访问(不然程序容易崩溃)。

QByteArray data_image QMutex mutex_prest我是定义在config.h里面的,可以根据实际使用自行安排。

void MyThread::run()
{
    receiver_udp=new QUdpSocket;
    receiver_udp->bind(00000,QUdpSocket::ShareAddress);  //绑定需要监听的端口
    connect(receiver_udp,SIGNAL(readyRead()),this,SLOT(processPendingDatagram()),Qt::DirectConnection);
    exec();
}

void MyThread::processPendingDatagram()
{
    while(receiver_udp->hasPendingDatagrams())  //拥有等待的数据报
    {
        QByteArray datagram;
        datagram.resize(receiver_udp->pendingDatagramSize());
        receiver_udp->readDatagram(datagram.data(),datagram.size());

        mutex_prest.lock();  //加锁

        //data_image是全局变量,这边datagram为一张图片的包,实际可能需对数据进行处理
        data_image.clear();
        data_image = datagram;

        mutex_prest.unlock();  //解锁
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
继承QQuickImageProvider类
头文件
#ifndef MYIMAGEPROVIDER_H
#define MYIMAGEPROVIDER_H

#include <QQuickImageProvider>
//#include <QQuickWindow>
#include <QImage>

class MyImageProvider : public QQuickImageProvider
{

public:
    MyImageProvider();
    ~MyImageProvider();

    QImage requestImage(const QString & id, QSize * size, const QSize & requestedSize);
};

#endif // MYIMAGEPROVIDER_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cpp
利用函数requestImage(const QString &id, QSize *size, const QSize &requestedSize)完成图片请求,在多个请求或者多个图片时,可以用 id 变量进行进一步判断。
#include "myimageprovider.h"
#include "config.h"
#include <QImageReader>
#include <QBuffer>

MyImageProvider::MyImageProvider()
    : QQuickImageProvider(QQuickImageProvider::Image)
{
}

MyImageProvider::~MyImageProvider()
{
}

QImage MyImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    //按IP和类型进行处理
    //qDebug() << "id: " << id;
    //QString type;
    //type=id.mid(0,id.indexOf(":"));
    //QString str;
    //str=id.mid(id.indexOf(":")+1,id.indexOf("/")-id.indexOf(":")-1);

    QImage image;

    if(data_image.size()!=0)
    {
        mutex_prest.lock();
        //QByteArray 转 QImage
        QBuffer buffer(&(data_image.image));
        buffer.open(QIODevice::ReadOnly);
        QImageReader reader(&buffer,"JPG");
        image = reader.read();
        mutex_prest.unlock();
    }
    else
    {
        //若图片数据为空,则加载默认图片
        image.load(":/bord/img/block.jpg");
    }

    return image;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
注册MyImageProvider
在main.cpp中将MyImageProvider注册到QML中。
MyImageProvider *myImg = new MyImageProvider();
QQmlApplicationEngine engine;
engine.addImageProvider(“MyProvider”, myImg);
engine.load(QUrl(QLatin1String(“qrc:/main.qml”)));

Image动态显示
cache是否缓存,设为false。默认为true
使用定时器动态刷新,定时时间根据具体接收效率和显示帧率设置。或者也可以采用信号与槽的方式通知刷新。
Image {
    id: img_preview
    cache: false;  //取消缓存
    width: 170;
    height: 100;
    source: "qrc:/bord/img/block.jpg" //默认图片
}

Timer{
    //定时器触发时间 单位毫秒
    interval: 100;
    //触发定时器
    running: true;
    //不断重复
    repeat: true;
    //定时器触发时执行
    onTriggered: {
        img_preview.source = "";
        img_preview.source = "image://myprovider/ip:xxx.xxx.xxx.xxx";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
小结
当某个变量被多个线程访问时,注意使用QMutex来保护访问安全。
Image在刷新source时,注意先置空,且取消缓存,不然会出现图片刷新无反应的情况,或者使用加随机数的方式
source = "image://myprovider/ip:"+Math.random();

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
————————————————
版权声明:本文为CSDN博主「我一板砖下去」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_22049783/article/details/81091766

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值