Как работает пример семплинга в примере с осциллографом qwt в проекте?
У меня возникли трудности в понимании примера осциллографа QWT. Я примерно понимаю большую часть программы, но не могу найти связь между классом семплирования и классом сюжета.
Похоже, что образцы диаграмм взяты из samplelingthread и предоставляются объекту QwtPlotCurve в классе plot.
Однако я не могу найти связь между объектом выборки и потоком сюжета. Но когда я изменяю значение частоты в объекте samplelingthread, оно применяется и появляется на объекте plot (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(). и я не могу найти связь между объектом графика и объектом выборки. Кто-нибудь может объяснить эту часть для меня?
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
}
}
Я воздержусь от использования этого примера как есть.
Сигнал / слот между двумя потоками заканчивается как QEvents в очереди событий Qt. Учитывая, что поток выборки создает значения очень быстро (например, каждые 10 мс), очевидно, что это не вариант.
Таким образом, должен быть общий буфер, где запись / чтение защищаются мьютексом - это то, чем является SignalData.
Мост между SignalData и кривой сделан CurveData, который реализует данный API. Если вам нравится, вы можете сравнить CurveData с идеей QAbstractItemModel.
Но применение осциллографа - это скорее демонстрация, чем пример. Он показывает, что возможно при очень низкой загрузке ЦП (прекрасно работает даже на Pi с разумной загрузкой ЦП) с использованием нескольких приемов.