Skip to main content
标签ad报错:该广告ID(9)不存在。
  主页 > Qt入门

一个Qt/C++ Demo,用于实现一个用于显示频谱图的控件效果

2023-04-23 浏览:
标签ad报错:该广告ID(7)不存在。 Code Demo

    #pragma once

#include 
#include 
#include 
#include 
#include 
#include 
#include 

class SpectrumWidget : public QWidget {
    Q_OBJECT
public:
    explicit SpectrumWidget(QWidget* parent = nullptr) :
        QWidget(parent),
        m_data(1000, 0),
        m_pixmap(QSize(1000, 300)),
        m_spectrumData(m_data.size()),
        m_timer(new QTimer(this))
    {
        // 设置定时器,控制波形图的刷新速度
        m_timer->setInterval(50);
        connect(m_timer, &QTimer::timeout, this, &SpectrumWidget::onTimeout);

        QHBoxLayout* layout = new QHBoxLayout();
        QLabel* label = new QLabel();
        layout->addWidget(label);
        setLayout(layout);
        m_label = label;

        // 初始化FFT
        m_plan = fftw_plan_r2r_1d(m_data.size(), m_data.data(), m_spectrumData.data(), FFTW_R2HC, FFTW_ESTIMATE);
    }

    ~SpectrumWidget() override {
        delete m_timer;
        fftw_destroy_plan(m_plan);
    }

    void start() {
        m_timer->start();
    }

    void stop() {
        m_timer->stop();
    }

private:
    void paintEvent(QPaintEvent* event) override {
        QPainter painter(this);
        painter.drawPixmap(rect(), m_pixmap);
    }

    void onTimeout() {
        // 更新数据
        for (int i = 1; i < m_data.size(); ++i) {
            m_data[i - 1] = m_data[i];
        }
        m_data[m_data.size() - 1] = rand() % 200;

        // 计算频谱
        fftw_execute(m_plan);

        // 更新图像
        QPixmap oldPixmap = m_pixmap;
        QPainter painter(&m_pixmap);
        painter.fillRect(m_pixmap.rect(), Qt::black);
        QColor color(0, 255, 0);
        painter.setPen(color);
        QPoint prevPoint(-1, -1);
        for (int i = 0; i < m_spectrumData.size() / 2; ++i) {
            int x = i * 2;
            int y = 300 - m_spectrumData[i];
            QPoint point(x, y);
            if (prevPoint.x() != -1) {
                painter.drawLine(prevPoint, point);
            }
            prevPoint = point;
        }

        if (oldPixmap.size() != m_pixmap.size()) {
            m_label->setFixedSize(m_pixmap.size());
        }
        m_label->setPixmap(m_pixmap);

        update();
    }

private:
    QVector m_data;
    QVector m_spectrumData;
    QPixmap m_pixmap;
    QTimer* m_timer;
    QLabel* m_label;
    fftw_plan m_plan;
};


该Demo继承自QWidget,实现了一个用于显示频谱图的控件。在该控件中,使用QVector来保存频谱图中每一点的数据以及用于计算频谱的原始数据,使用QPixmap来绘制频谱图。同时,通过设置QTimer来控制频谱图的刷新速度,并在定时器触发时更新数据、计算频谱以及更新图像。可以通过调用start()函数启动频谱图并调用stop()函数停止频谱图。 需要注意的是,该Demo使用了fftw库来计算傅里叶变换,需要在项目中添加相关的头文件和链接库。