#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来控制荧光频谱图的刷新速度,并在定时器触发时生成荧光信号数据、计算频谱以及更新图像。需要注意的是,由于荧光信号数据具有周期性,因此可以通过设置荧光频率来控制荧光信号数据的频率变化。
在频谱图的绘制过程中,为了更好地显示荧光频谱图的峰值,可以对峰值进行取对数处理并调整振幅范围。