qwt示波器示例的samplingthread class在项目中是如何工作的?

how does qwt oscilloscope example's samplingthread class work in the project?

我很难理解 qwt 示波器示例。 我大致了解了大部分程序,但我找不到 samplingthread class 和 plot class.

之间的联系

图表样本似乎来自 samplingthread,并提供给 plot class 中的 QwtPlotCurve 对象。

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

下面是部分代码(来自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()。 而且我找不到 plot 对象和 samplingthread 对象之间的联系。 谁能帮我解释一下这部分?

有一个基于 class 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
    }
}

我将避免按原样使用此示例。

2 个线程之间的

signal/slot 最终作为 Qt 事件队列中的 QEvents。考虑到采样线程创建值的速度非常快(f.e 每 10 毫秒),很明显,这是没有选择的。

因此需要一个共享缓冲区,其中 writing/reading 由互斥锁保护 - 这就是 SignalData。

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

但示波器应用与其说是示例,不如说是演示。它显示了使用一些技巧以非常低的 CPU 使用率(即使在 Pi 上以合理的 CPU 使用率也能很好地运行)的可能性。