先看效果
录制_2022_08_11_14_37_25_628
在网上找了一圈, 好多人写的资料敝竹自珍,还要收费真是无语。还有些需要用第三方库,真是没有必要。qt可以直接实现这些功能
音乐播放器的实现我就不贴了, 网上好多例子,我主要写下频谱的实现。
1. 获取波形数据
// 音频获取probe = new QAudioProbe(this);connect(probe, &QAudioProbe::audioBufferProbed, this,&MainWindow::processBuffer);probe->setSource(music_player); // 传入音乐播放器void MainWindow::processBuffer(const QAudioBuffer &buffer)
{if(buffer.sampleCount() / 2 > 0)ui->label_boxingtu->drawAudioPxm(buffer);
}
2. 主界面上增加Qlabel 控件,新增一个类MyQLabel , 继承QLabel,做控件提升。
3. 在 MyQLabel 类中, 重写 paintEvent 。
MyQLabel::MyQLabel(QWidget *parent):QLabel(parent)
{graphicStyle = GraphicStyle::PingPu;
}void MyQLabel::drawAudioPxm(const QAudioBuffer &buffer)
{m_buffer = buffer;update();
}void MyQLabel::paintEvent(QPaintEvent *ev)
{int count = m_buffer.sampleCount() / 2;if(count <= 0)return;QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing); // 抗锯齿if(graphicStyle == GraphicStyle::PingPu )drawWaveformFigure(painter);else if (graphicStyle == GraphicStyle::ZhuZhuangTu)drawHistogram(painter);else if (graphicStyle == GraphicStyle::ZhengTi)drawOverallVolatility(painter);
}// 频谱效果
void MyQLabel::drawWaveformFigure(QPainter &painter)
{const qint32 *data = m_buffer.constData<qint32>();int count = m_buffer.sampleCount() / 2;QPen pen = painter.pen();pen.setWidth(1);pen.setColor(Qt::blue);painter.setPen(pen);float xScale = (float)this->width() / count;float center = (float)this->height() / 2;for(int i = 1; i < count; i++){painter.drawLine((i - 1) * xScale,center + ((float)(data[i-1]) / INT_MAX * center),i * xScale,center + ((float)(data[i]) / INT_MAX * center) );}
}// 柱状图效果
void MyQLabel::drawHistogram(QPainter &painter)
{const qint32 *data = m_buffer.constData<qint32>();int count = m_buffer.sampleCount() / 2;int step = count / 50;QVector <qreal> vecData;for(int i = 0; i < 51; i++){int number = 0;qreal sum = 0;for (int j = 0; j < step; j++){if(i * 50 + j >= count)break;qreal value = (qreal)(data[i * 50 + j]) / INT_MAX * this->height();if(value > 0){sum += value;number++;}}if(number > 0)vecData.push_back(sum / number);elsevecData.push_back(0);}qreal rectangleWidth = (qreal)this->width() / vecData.count(); // 图形加间隙的宽度qreal clearanceWidth = rectangleWidth / 4; // 间隙宽度qreal shapeWidth = rectangleWidth - clearanceWidth; // 图形宽度QPen pen = painter.pen();pen.setWidth(shapeWidth);pen.setColor(Qt::red);painter.setPen(pen);for(int i = 0; i < vecData.count(); i++){painter.drawLine(i * rectangleWidth + rectangleWidth* 0.5,this->height() - vecData[i],i * rectangleWidth + rectangleWidth* 0.5,this->height());}
}// 整体效果
void MyQLabel::drawOverallVolatility(QPainter &painter)
{const qint32 *data = m_buffer.constData<qint32>();int count = m_buffer.sampleCount() / 2;qreal maxValue = 0; // 取最大值for(int i = 1; i < count; i++){qreal value = (qreal)(data[i]) / INT_MAX * this->height();maxValue = qMax(value,maxValue);}qreal rectangleWidth = (qreal)this->width() / 10; // 图形加间隙的宽度qreal clearanceWidth = rectangleWidth / 4; // 间隙宽度qreal shapeWidth = rectangleWidth - clearanceWidth; // 图形宽度for(int i = 0; i < 10; i++){QRect rect(i * rectangleWidth + clearanceWidth*0.5, 0, shapeWidth, this->height());QLinearGradient gradient(rect.x(), rect.y(),rect.x(), rect.y() + rect.height());gradient.setColorAt(0.0, Qt::red);gradient.setColorAt(0.3, Qt::green);gradient.setColorAt(0.6, Qt::yellow);gradient.setColorAt(1.0, Qt::blue);painter.setPen(Qt::NoPen);gradient.setSpread(QGradient::ReflectSpread);painter.setBrush(gradient); // QBrush(const QGradient &gradient)painter.drawRect(rect);// 去掉顶部QBrush brush = painter.brush();brush.setStyle(Qt::SolidPattern);brush.setColor(Qt::white);painter.setBrush(brush);painter.drawRect(i * rectangleWidth + clearanceWidth*0.5, 0, shapeWidth, this->height() - maxValue);}
}void MyQLabel::setGraphicStyle(const GraphicStyle &value)
{graphicStyle = value;
}
最近好多人照着我这个写完后运行报错,我在网上也查了下,应该是QT版本的兼容问题,下面是我用的 QT 版本信息, 上面的代码以及发的源码都是我自己写的,运行后没问题才发出来。
需要源码的,把邮箱留下,我看到后会给你发的。