Qt graphicsview 实现大量线阵、列数据Item实时刷新的方案1(亲测)

方案1 基于advance

收到新数据后,通过advance触发scene中所有item的同向偏移,然后在开头插入最新数据

setp1.在线程中模拟线阵数据生成

此处使用QImage生成线阵数据类,其可以通过指针可以实现更快速的像素级操作,而且相对setPixel来赋值像素的效率更高。这里的线数据也可以改成一次多线,修改宽度即可。

QPixmap moniData::generateLine(int width)
{
    QImage img(width,height, QImage::Format_RGB32);
    //注意像素遍历赋值与图像格式有关,RGB32格式中一个像素占4个8位,其他格式可能需要更改
    uchar*  p_w_picpathbits_32 = img.bits();
    uchar a = qrand()%255;
    for(int j = 0; j < width; j++)
    {
        for(int i = 0; i < height; i++)
        {
            p_w_picpathbits_32[i*width*4 + (width-j-1)*4 + 2] = a;
            p_w_picpathbits_32[i*width*4 + (width-j-1)*4 + 1] = a;
            p_w_picpathbits_32[i*width*4 + (width-j-1)*4] = a;
        }
    }
    emit sendMoniData(QPixmap::fromImage(img));
    return QPixmap::fromImage(img);
}
step2. 重写Item的advance函数

mygraphicspixmapitem.h

#ifndef MYGRAPHICSPIXMAPITEM_H
#define MYGRAPHICSPIXMAPITEM_H

#include <QGraphicsPixmapItem>

class myGraphicsPixmapItem : public QGraphicsPixmapItem
{
public:
    myGraphicsPixmapItem(QPixmap);
    int posx = 0;


protected:
     void advance(int phase);
};

#endif // MYGRAPHICSPIXMAPITEM_H

mygraphicspixmapitem.c

#include "mygraphicspixmapitem.h"

myGraphicsPixmapItem::myGraphicsPixmapItem(QPixmap pixmap)
{
    this->setPixmap(pixmap);
}

void myGraphicsPixmapItem::advance(int phase)
{
    if(!phase)
    {
        this->setPos(++posx, this->pos().y());
    }
}

step3.设置scene触发advance的信号move(),这个信号自定义
connect(this, &MyGraphiscView::move, m_pScene, &QGraphicsScene::advance);
step4.接收到新数据后,发送move(),移动之前的数据,并在起点插入新数据
void MyGraphiscView::updateView(QPixmap linedata)
{
    emit move();
    myGraphicsPixmapItem *item = new myGraphicsPixmapItem(linedata);
    item->setPos(0,100);//高度看自己需求,可以实现居中
    m_pScene->addItem(item);
}
step5.删除旧数据,防止内存泄漏

不停的插入新数据会不停的申请内存,根据自己需求保留一定长度即可,将旧数据删除防止内存泄漏。
方法1
通过itemAt找到旧数据并删除

void MyGraphiscView::updateView(QPixmap linedata)
{
	//这里设的最大宽度500,可自行调整
	emit move();
	myGraphicsPixmapItem *item = new myGraphicsPixmapItem(linedata);
	item->setPos(0,100);
	m_pScene->addItem(item);
	if(m_pScene->items().size()>=500)
	{
	    QTransform transform;
	    m_pScene->removeItem(m_pScene->itemAt(500,100, transform));
	}
}

方法2
将生成的数据存到QList、QVector或vector中做一个队列,先进先出,后进后出。虽然有链表和顺序表之间的区别,经过测试最终效率都差不多。

void MyGraphiscView::updateView(QPixmap linedata)
{
	emit move();
	myGraphicsPixmapItem *item = new myGraphicsPixmapItem(linedata);
	item->setPos(0,100);
	m_pScene->addItem(item);
	m_lineBuffer.append(item);
	if(m_pScene->items().size()>=500)
	{
	    m_pScene->removeItem(m_lineBuffer.front());
	    delete m_lineBuffer.front();
	    m_lineBuffer.pop_front();
	}
}

实现效果

在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值