方案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();
}
}