1. 自定义控件之音响特效

本文详细介绍了如何在QtCreator中创建一个自定义控件CCBarVolume,模拟传统音响中随着声音变化的方格动画。通过QPainter和QGraphicsScene实现图形绘制,包括背景渐变、进度条和手动拖动功能。
摘要由CSDN通过智能技术生成

介绍:

今天学习下使用qt creator进行控件的自定义,看到网上也有很多自定义控件的演示,看着他的效果自己也尝试写写。今天要做的是这个控件是一个音响效果,小时候家里的音响上,随着声音的播放,会有类似于一堆方格子上下跳动。今天需要做的就是这个样式,并且,可以手动拖动方格子上下走动。效果图大体如下:
在这里插入图片描述

代码详解:

这个功能比较简单,功能主要分为两个类去实现,从下往上来介绍下这个结构,每个大的柱形,都是一个CCBarVolume 对象,里边的可以配置需要多少个方格在跳动,并且使用QPainter进行颜色的绘制,定义结构

#ifndef CCBARVOLUME_H
#define CCBARVOLUME_H

#include <QWidget>
#include <QPainter>
#include <QList>
#include <QMouseEvent>

class CCBarVolume : public QWidget
{
    Q_OBJECT
public:
    explicit CCBarVolume(QWidget *parent = nullptr);

    void setBarColorStart(QColor );
    void setBarColorMid(QColor );
    void setBarColorEnd(QColor );

    void setCurrentValue(int value);
protected:
    void paintEvent(QPaintEvent *event);

    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);

private:
    void drawBg(QPainter * painter);
    void drawBarBg(QPainter * painter);
    void drawBar(QPainter * painter);
    QLinearGradient getLinearGradient();
    double getLeftY(int idx);
    double getRectWidth();
    double getRectHeight();


private:
    int m_value ;
    int m_space ; //距离边框的空隙
    int m_interval;// 相邻矩阵之间的间距
    int m_rectNum ;//需要的矩阵个数

    bool m_isPressOper;//是否手动操作
    bool m_isVertical;//是否是垂直方向

    double m_rectWidth ;//
    double m_rectHeigth;//步长
    QList<QRectF> m_rects;

    QColor bgColorStart;    //背景渐变开始颜色
    QColor bgColorEnd;      //背景渐变结束颜色
    QColor barBgColor;      //进度背景颜色

    QColor barColorStart;   //进度渐变开始颜色
    QColor barColorMid;     //进度渐变中间颜色
    QColor barColorEnd;     //进度渐变结束颜色

signals:

};

#endif // CCBARVOLUME_H
#include "CCBarVolume.h"
#include <QLinearGradient>
#include <QDebug>

CCBarVolume::CCBarVolume(QWidget *parent) : QWidget(parent)
{
    m_space = 5;
    m_interval = 3;
    m_rectNum = 10;

    bgColorStart = QColor(60, 60, 60);
    bgColorEnd = QColor(100, 100, 100);
    barBgColor = QColor(167, 167, 167);

    barColorStart = QColor(85, 255, 0);
    barColorMid = QColor(249, 216, 47);
    barColorEnd = QColor(249, 107, 24);
}

void CCBarVolume::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //画背景
    drawBg(&painter);

    drawBarBg(&painter);

    drawBar(&painter);
}

void CCBarVolume::drawBg(QPainter * painter)
{
    painter->save();

    QLinearGradient gradient = getLinearGradient();
    gradient.setColorAt(0, bgColorStart);
    gradient.setColorAt(1, bgColorEnd);
    painter->setBrush(gradient);
    painter->drawRect(rect());


    painter->restore();
}


void CCBarVolume::drawBarBg(QPainter * painter)
{
    painter->save();

    painter->setPen(Qt::NoPen);
    painter->setOpacity(0.4);
    QLinearGradient gradient = getLinearGradient();
    gradient.setColorAt(0, barBgColor);
    gradient.setColorAt(1, barBgColor);
    painter->setBrush(gradient);

    m_rects.clear();

    for(int i = 0 ; i < m_rectNum; i++) {
       auto leftx = m_interval;
       auto lefty = getLeftY(i);
       auto r = QRectF(leftx,lefty ,   getRectWidth(),getRectHeight());
        m_rects << r;

        painter->drawRect(r);
    }



    painter->restore();
}


void CCBarVolume::drawBar(QPainter * painter)
{
    painter->save();

    painter->setPen(Qt::NoPen);
    painter->setOpacity(1.0);
    QLinearGradient gradient = getLinearGradient();
    gradient.setColorAt(0, barColorStart);
    gradient.setColorAt(0.5, barColorMid);
    gradient.setColorAt(1, barColorEnd);
    painter->setBrush(gradient);


    for(int i = 0 ; i <= m_value; i++){
        auto leftx = m_interval;
        auto lefty = getLeftY(i);
        auto r = QRectF(leftx,lefty ,   getRectWidth(),getRectHeight());
        painter->drawRect(r);
    }

    painter->restore();
}

QLinearGradient CCBarVolume::getLinearGradient()
{
    QLinearGradient gradient (0, 0, width(), height()); ;
    return gradient;
}

double CCBarVolume::getLeftY(int idx)
{

    return height() - (idx +1) * getRectHeight() - (idx +1)  * m_interval;
}

double CCBarVolume::getRectWidth()
{
    return width() - 2 * m_interval;
}

double CCBarVolume::getRectHeight(){
    return   (static_cast<double>(height()) -  static_cast<double>((m_rectNum + 1) * m_interval)  ) / static_cast<double>(m_rectNum) ;
}

void CCBarVolume::setBarColorStart(QColor r)
{
    barColorStart = r;
}

void CCBarVolume::setBarColorMid(QColor r)
{
    barColorMid =r;
}

void CCBarVolume::setBarColorEnd(QColor r)
{
    barColorEnd = r;
}

void CCBarVolume::setCurrentValue(int value)
{
    qDebug() << "m_value = " << m_value << "value = " << value ;
    if (m_value != value) {
        m_value =  value ;// (value > m_value ? m_value : value);

    }
    this->update();
}

void CCBarVolume::mousePressEvent(QMouseEvent *event)
{
    mouseMoveEvent(event);
}

void CCBarVolume::mouseMoveEvent(QMouseEvent *event)
{
//    if(!m_isPressOper){
//        return ;
//    }
    QPoint p = event->pos();
    qDebug() << "mouseMoveEvent  pos = " << p;

    int count = m_rects.count();
    for (int i = 0; i < count; ++i) {
        QRectF rect = m_rects.at(i);
        //这里可以自行增加代码过滤到中间才切换
        if (rect.contains(p)) {
            setCurrentValue(i);
            break;
        }
    }
}


网上一层是对这个CCBarVolume的管理与调用,里边是有定时器来刷新这个柱子上每秒钟需要多少个方格块进行jump,

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QList>
#include "CCBarVolume.h"
#include <QTimer>

class CCBarVolume ;

QT_BEGIN_NAMESPACE
namespace Ui { class frmbarvolume; }
QT_END_NAMESPACE

class frmbarvolume : public QWidget
{
    Q_OBJECT

public:
    frmbarvolume(QWidget *parent = nullptr);
    ~frmbarvolume();
private:
    void initWidget();
private slots:
    void updateValue();
private:
    Ui::frmbarvolume *ui;
    QList<CCBarVolume*> m_bars;
    QTimer*  m_pTimer ;
};
#endif // WIDGET_H
#include "frmbarvolume.h"
#include "ui_frmbarvolume.h"
#include <QDebug>

frmbarvolume::frmbarvolume(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::frmbarvolume)
{
    ui->setupUi(this);

    initWidget();
}

frmbarvolume::~frmbarvolume()
{
    for (auto ptr : m_bars) {
        if(ptr == NULL){
            continue;
        }
        delete ptr;
        ptr = NULL;
    }

    if(m_pTimer){
        delete m_pTimer;
        m_pTimer = NULL;
    }

    delete ui;
}

void frmbarvolume::initWidget()
{
    for(int i = 0; i < 5; i++){
        CCBarVolume* bar = new CCBarVolume;
        if (!bar){
            return ;
        }

        m_bars << bar;
    }


    m_bars.at(1)->setBarColorStart(QColor(255, 64, 64));
    m_bars.at(1)->setBarColorMid(QColor(255, 127, 36));
    m_bars.at(1)->setBarColorEnd(QColor(238, 238, 0));

    m_bars.at(2)->setBarColorStart(QColor(24, 189, 155));
    m_bars.at(2)->setBarColorMid(QColor(140, 238, 237));
    m_bars.at(2)->setBarColorEnd(QColor("#2E8B57"));

    m_bars.at(3)->setBarColorStart(QColor("#8A2BE2"));
    m_bars.at(3)->setBarColorMid(QColor("#836FFF"));
    m_bars.at(3)->setBarColorEnd(QColor("#7B68EE"));

    foreach (CCBarVolume* bar, m_bars) {
        ui->gridLayout->removeWidget(bar);
    }

    int count = m_bars.count();
    for(int i = 0; i < count;i++) {
        ui->gridLayout->addWidget(m_bars.at(i),  0,i);
    }

    m_pTimer = new QTimer();

    int interval = 1000;
    m_pTimer->setInterval(interval);
    connect(m_pTimer,SIGNAL(timeout()),this,SLOT(updateValue() ));
    m_pTimer->start();
}

void frmbarvolume::updateValue()
{
    int count = m_bars.count();
    for(int i = 0; i < count;i++) {
        CCBarVolume* bar =  m_bars.at(i);
        bar->setCurrentValue(rand() % 10);
    }
}

总结:

这里算是贴出来了所有的实现了,还有部分的功能使用进度条去调整他的跳动块数这里就没有往下写,实现了最主要的功能就好了,剩下的偷个懒也未尝不可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值