Qt实现仪器仪表中的刻度循环移动

问题描述

有些仪表中,需要刻度能循环移动,比如显示角度的仪表,需要刻度循环移动如下视频所示。

刻度循环移动

问题解决

将循环移动的整幅图像绘制在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);
}

完整代码可下载绑定资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平凡的大白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值