qt示波器示例采样线程类在项目中是如何工作的?

Posted

技术标签:

【中文标题】qt示波器示例采样线程类在项目中是如何工作的?【英文标题】:how does qwt oscilloscope example's samplingthread class work in the project? 【发布时间】:2015-12-14 13:10:32 【问题描述】:

我很难理解 qwt 示波器示例。 我大致了解了大部分程序,但我找不到采样线程类和绘图类之间的联系。

图表样本似乎来自采样线程,并提供给绘图类中的 QwtPlotCurve 对象。

但是我找不到采样线程对象和绘图对象之间的联系。但是当我更改采样线程对象中的频率值时,它会应用并出现在绘图对象(画布)上。

以下是部分代码(来自 main.cpp),我不太明白,但请参考完整项目(我认为需要解压缩),下载地址为 http://sourceforge.net/projects/qwt/files/qwt/6.1.2/.

int main( int argc, char **argv )

QApplication app( argc, argv );
app.setPalette( Qt::darkGray );

MainWindow window;
window.resize( 800, 400 );

SamplingThread samplingThread;
samplingThread.setFrequency( window.frequency() ); // window.frequency()'s type is double 
samplingThread.setAmplitude( window.amplitude() ); // window.amplitude()'s type is double
samplingThread.setInterval( window.signalInterval() ); // window.signalInterval()'s type is double

window.connect( &window, SIGNAL( frequencyChanged( double ) ),
    &samplingThread, SLOT( setFrequency( double ) ) );
window.connect( &window, SIGNAL( amplitudeChanged( double ) ),
    &samplingThread, SLOT( setAmplitude( double ) ) );
window.connect( &window, SIGNAL( signalIntervalChanged( double ) ),
    &samplingThread, SLOT( setInterval( double ) ) );

window.show();

samplingThread.start();
window.start();

bool ok = app.exec();

samplingThread.stop();
samplingThread.wait( 1000 );

return ok;

上面的window.start() 等于plot->start()。 而且我找不到绘图对象和采样线程对象之间的联系。 谁能帮我解释一下这部分?

【问题讨论】:

那些window.connect 是连接到以后在组件之间传输数据的信号和插槽。如果你不熟悉这个机制,就像设置回调一样。 信号来自位于 MainWindows 中的 qwt 小部件,它链接到 samplingThread 的函数。我的问题是情节和采样线程之间的联系。因为当 samplingThread 的成员变量(例如频率)值发生变化时,它会被应用并显示在绘图上。 所以你的意思是另一种方式thread -> UI?这段代码没有显示任何有用的东西。 您可以从我发布的链接下载完整的项目。在问题的最后,我写了“window.start() 等于 plot->start()” 如果你再次看到上面的代码,你会发现“samplingThread.start(); window.start();”两个对象调用自己的启动函数,但我找不到对象之间的联系。 【参考方案1】:

两个线程之间的信号/槽最终作为 Qt 事件队列中的 QEvents。考虑到采样线程非常快地创建值(f.e 每 10 毫秒),很明显,这是没有选择的。

因此需要一个共享缓冲区,其中写入/读取由互斥体保护 - 这就是 SignalData。

SignalData 和曲线之间的桥梁由 CurveData 完成,它实现了给定的 API。如果您愿意,可以将 CurveData 与 QAbstractItemModel 的想法进行比较。

但示波器应用程序更多的是演示而不是示例。它显示了在 CPU 使用率非常低的情况下(即使在具有合理 CPU 使用率的 Pi 上也能很好地运行)的可能性,并使用了一些技巧。

【讨论】:

【参考方案2】:

有一个基于类SignalData 的奇怪单例模式的使用。 首先是单例:

class CurveData: public QwtSeriesData<QPointF>

public:
    const SignalData &values() const;
    SignalData &values();
...
;

const SignalData &CurveData::values() const

    return SignalData::instance();


QPointF CurveData::sample( size_t i ) const

    return SignalData::instance().value( i );

一方面

Plot::Plot( QWidget *parent ):

    d_curve = new QwtPlotCurve();
    ...
    d_curve->setData( new CurveData() ); //singleton being used inside each curvedata
    ...

另一方面

void SamplingThread::sample( double elapsed )

    if ( d_frequency > 0.0 )
    
        const QPointF s( elapsed, value( elapsed ) );
        SignalData::instance().append( s ); //singleton being used
    

我不会照原样使用这个例子。

【讨论】:

感谢您查看代码。我想要的只是我们经常讨论的 SamplingThread 和绘图对象之间的联系。你能找到并详细解释一下吗? @Jackson 仍然不清楚,因为我忘了添加一段代码。有一个 SignalData 隐藏着一个符号,它可以完成所有的魔法。他们在哪里懒得使用信号或共享对象?不知道。

以上是关于qt示波器示例采样线程类在项目中是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

示波器基本原理之二:采样率

示波器(ADC)的采样率怎么理解?

示波器入门之采样率存储深度

示波器的选型要素

示波器入门手册

ADC采样两路信号时,如何正确显示两路波形?