介绍:
今天学习下使用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);
}
}
总结:
这里算是贴出来了所有的实现了,还有部分的功能使用进度条去调整他的跳动块数这里就没有往下写,实现了最主要的功能就好了,剩下的偷个懒也未尝不可。