问题描述
有些仪表中,需要刻度能循环移动,比如显示角度的仪表,需要刻度循环移动如下视频所示。
刻度循环移动
问题解决
将循环移动的整幅图像绘制在QImage中,显示固定范围,将图像中像素数据循环移动,更新显示,即可实现循环移动的效果。
本文讲述如何用QGraphicsItem实现以上视频中的刻度循环移动
1、在QImage上均匀绘制出完整的刻度图形
2、在Item图形项上部分显示图形固定区域
3、利用QImage操纵像素的方法,使图形中的像素循环移动
代码实现
从 QGraphicsObject派生出GraphItem,以便可以使用信号和槽,如下所示。
头文件
#ifndef GRAPHITEM_H
#define GRAPHITEM_H
#include <QGraphicsObject>
class QImage;
class GraphItem : public QGraphicsObject
{
Q_OBJECT
public:
explicit GraphItem(QGraphicsItem *parent = nullptr);
private:
void moveRight(int num=5);
void moveLeft(int num=5);
public slots:
void slt_update();
void setValue(double value);
protected:
virtual QRectF boundingRect() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);
signals:
public slots:
private:
double m_width=480;
double m_height=50;
QImage *m_image=NULL;
QRectF rectF;
int m_num=0;
QImage img;
};
#endif // GRAPHITEM_H
实现的cpp文件
#include "graphitem.h"
#include<QPainter>
GraphItem::GraphItem(QGraphicsItem *parent) : QGraphicsObject(parent)
{
m_image=new QImage(m_width*3,m_height,QImage::Format_ARGB32);
m_image->fill(Qt::black);
rectF=QRectF(0,0,m_width+1,m_height);
QPainter p(m_image);
QPen pen(Qt::white);
pen.setWidthF(0.5);
p.setPen(pen);
QPointF startPos(5,15);
for(int i=0;i<120;i++)
{
QPointF pos=startPos+QPointF(12*i,10);
if(i%5==0)
{
p.drawLine(pos,pos+QPointF(0,10));
QRectF rect(0,0,40,15);
rect.moveCenter(startPos+QPointF(12*i,0));
p.drawText(rect,Qt::AlignCenter,QString("%1").arg(3*i,1,'f',0));
}
else
{
p.drawLine(pos+QPointF(0,5),pos+QPointF(0,10));
}
}
p.drawLine(0,35,m_width*3-1,35);
moveRight(5);
moveLeft(m_width/2);
m_num=0;
img=m_image->copy();
}
void GraphItem::setValue(double value)
{
const uchar* bits_img=img.bits();
uchar* bits_image=m_image->bits();
memcpy(bits_image,bits_img,img.byteCount());
// int num=(value)*4-m_num;
// if(num>0)
// {
// moveRight(qAbs(num));
// }
// else {
// moveLeft(qAbs(num));
// }
// m_num+=num;
moveRight(value*4);
update();
}
void GraphItem::moveRight(int num)
{
int image_width=m_image->width();
int image_height=m_image->height();
for(int i=0;i<image_height;i++)
{
QRgb* buff=(QRgb*)m_image->scanLine(i);
QRgb temp[num];
memmove(temp,buff,num*sizeof(QRgb));//
memmove(buff,buff+num,(image_width-num)*sizeof(QRgb));
memmove(buff+image_width-num-1,temp,(num)*sizeof(QRgb));
}
}
void GraphItem::moveLeft(int num)
{
int image_width=m_image->width();
int image_height=m_image->height();
for(int i=0;i<image_height;i++)
{
QRgb* buff=(QRgb*)m_image->scanLine(i);
QRgb temp[num];
memmove(temp,buff+image_width-num-1,num*sizeof(QRgb));//
memmove(buff+num,buff,(image_width-num)*sizeof(QRgb));
memmove(buff,temp,(num)*sizeof(QRgb));
}
}
void GraphItem::slt_update()
{
}
QRectF GraphItem::boundingRect() const
{
QRectF rectF=QRectF(0,0,m_width+1,m_height);
rectF.moveCenter(QPointF(0,0));
return rectF;
}
void GraphItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QPixmap pixmap=QPixmap::fromImage(*m_image);
painter->drawPixmap(boundingRect(),pixmap,rectF);
// QRectF rect(0,0,60,25);
// rect.moveCenter(QPointF(0,-10));
// painter->setBrush(QColor(255,0,0,255));
// painter->drawRect(rect);
// painter->drawText(rect,Qt::AlignCenter,QString::number(m_value,'f',2));
QPolygonF polygon;
polygon<<QPointF(0.5,10)<<QPointF(-4.5,23)<<QPointF(5.5,23);
painter->setBrush(QColor(0,0,255,255));
painter->setPen(Qt::NoPen);
painter->drawPolygon(polygon);
}
完整代码可下载绑定资源