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

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

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

   #pragma once

   #include <QWidget>
   #include <QHBoxLayout>
   #include <QLabel>
   #include <QPixmap>
   #include <QPainter>
   #include <QTimer>
   #include <fftw3.h>
   #include <cmath>
   
   class FluorescenceSpectrumWidget : public QWidget {
       Q_OBJECT
   public:
       explicit FluorescenceSpectrumWidget(QWidget* parent = nullptr) :
           QWidget(parent),
           m_data(1024, 0),
           m_pixmap(QSize(1024, 300)),
           m_spectrumData(m_data.size()),
           m_timer(new QTimer(this))
       {
           // 设置定时器,控制频谱图的刷新速度
           m_timer->setInterval(50);
           connect(m_timer, &QTimer::timeout, this, &FluorescenceSpectrumWidget::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);
       }
   
       ~FluorescenceSpectrumWidget() 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() {
           // 更新数据
           const double pi = 3.14159265358979323846;
           double frequency = rand() % 20 + 10; // 荧光频率
           for (int i = 0; i < m_data.size(); ++i) {
               m_data[i] = 50 * sin(2 * pi * i / frequency) + rand() % 5; // 生成荧光信号数据
           }
   
           // 计算频谱
           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 - log(m_spectrumData[i] + 1) * 50; // 取对数处理并调整振幅范围
               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<double> m_data;
       QVector<double> m_spectrumData;
       QPixmap m_pixmap;
       QTimer* m_timer;
       QLabel* m_label;
       fftw_plan m_plan;
   };
   
   该Demo继承自QWidget,实现了一个用于显示荧光频谱图的控件。在该控件中,使用QVector来保存荧光频谱图中每一点的数据以及用于计算频谱的原始数据,使用QPixmap来绘制荧光频谱图。同时,通过设置QTimer来控制荧光频谱图的刷新速度,并在定时器触发时生成荧光信号数据、计算频谱以及更新图像。需要注意的是,由于荧光信号数据具有周期性,因此可以通过设置荧光频率来控制荧光信号数据的频率变化。

   在频谱图的绘制过程中,为了更好地显示荧光频谱图的峰值,可以对峰值进行取对数处理并调整振幅范围。