Как работает пример семплинга в примере с осциллографом 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 с разумной загрузкой ЦП) с использованием нескольких приемов.

Другие вопросы по тегам