Released version 6.1.3
This commit is contained in:
commit
a94503cb82
1885 changed files with 276310 additions and 0 deletions
27
examples/oscilloscope/curvedata.cpp
Normal file
27
examples/oscilloscope/curvedata.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include "curvedata.h"
|
||||
#include "signaldata.h"
|
||||
|
||||
const SignalData &CurveData::values() const
|
||||
{
|
||||
return SignalData::instance();
|
||||
}
|
||||
|
||||
SignalData &CurveData::values()
|
||||
{
|
||||
return SignalData::instance();
|
||||
}
|
||||
|
||||
QPointF CurveData::sample( size_t i ) const
|
||||
{
|
||||
return SignalData::instance().value( i );
|
||||
}
|
||||
|
||||
size_t CurveData::size() const
|
||||
{
|
||||
return SignalData::instance().size();
|
||||
}
|
||||
|
||||
QRectF CurveData::boundingRect() const
|
||||
{
|
||||
return SignalData::instance().boundingRect();
|
||||
}
|
16
examples/oscilloscope/curvedata.h
Normal file
16
examples/oscilloscope/curvedata.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <qwt_series_data.h>
|
||||
#include <qpointer.h>
|
||||
|
||||
class SignalData;
|
||||
|
||||
class CurveData: public QwtSeriesData<QPointF>
|
||||
{
|
||||
public:
|
||||
const SignalData &values() const;
|
||||
SignalData &values();
|
||||
|
||||
virtual QPointF sample( size_t i ) const;
|
||||
virtual size_t size() const;
|
||||
|
||||
virtual QRectF boundingRect() const;
|
||||
};
|
95
examples/oscilloscope/knob.cpp
Normal file
95
examples/oscilloscope/knob.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
#include "knob.h"
|
||||
#include <qwt_math.h>
|
||||
#include <qpen.h>
|
||||
#include <qwt_knob.h>
|
||||
#include <qwt_round_scale_draw.h>
|
||||
#include <qwt_scale_engine.h>
|
||||
#include <qlabel.h>
|
||||
#include <qevent.h>
|
||||
|
||||
Knob::Knob( const QString &title, double min, double max, QWidget *parent ):
|
||||
QWidget( parent )
|
||||
{
|
||||
QFont font( "Helvetica", 10 );
|
||||
|
||||
d_knob = new QwtKnob( this );
|
||||
d_knob->setFont( font );
|
||||
|
||||
QwtScaleDiv scaleDiv =
|
||||
d_knob->scaleEngine()->divideScale( min, max, 5, 3 );
|
||||
|
||||
QList<double> ticks = scaleDiv.ticks( QwtScaleDiv::MajorTick );
|
||||
if ( ticks.size() > 0 && ticks[0] > min )
|
||||
{
|
||||
if ( ticks.first() > min )
|
||||
ticks.prepend( min );
|
||||
if ( ticks.last() < max )
|
||||
ticks.append( max );
|
||||
}
|
||||
scaleDiv.setTicks( QwtScaleDiv::MajorTick, ticks );
|
||||
d_knob->setScale( scaleDiv );
|
||||
|
||||
d_knob->setKnobWidth( 50 );
|
||||
|
||||
font.setBold( true );
|
||||
d_label = new QLabel( title, this );
|
||||
d_label->setFont( font );
|
||||
d_label->setAlignment( Qt::AlignTop | Qt::AlignHCenter );
|
||||
|
||||
setSizePolicy( QSizePolicy::MinimumExpanding,
|
||||
QSizePolicy::MinimumExpanding );
|
||||
|
||||
connect( d_knob, SIGNAL( valueChanged( double ) ),
|
||||
this, SIGNAL( valueChanged( double ) ) );
|
||||
}
|
||||
|
||||
QSize Knob::sizeHint() const
|
||||
{
|
||||
QSize sz1 = d_knob->sizeHint();
|
||||
QSize sz2 = d_label->sizeHint();
|
||||
|
||||
const int w = qMax( sz1.width(), sz2.width() );
|
||||
const int h = sz1.height() + sz2.height();
|
||||
|
||||
int off = qCeil( d_knob->scaleDraw()->extent( d_knob->font() ) );
|
||||
off -= 15; // spacing
|
||||
|
||||
return QSize( w, h - off );
|
||||
}
|
||||
|
||||
void Knob::setValue( double value )
|
||||
{
|
||||
d_knob->setValue( value );
|
||||
}
|
||||
|
||||
double Knob::value() const
|
||||
{
|
||||
return d_knob->value();
|
||||
}
|
||||
|
||||
void Knob::setTheme( const QColor &color )
|
||||
{
|
||||
d_knob->setPalette( color );
|
||||
}
|
||||
|
||||
QColor Knob::theme() const
|
||||
{
|
||||
return d_knob->palette().color( QPalette::Window );
|
||||
}
|
||||
|
||||
void Knob::resizeEvent( QResizeEvent *event )
|
||||
{
|
||||
const QSize sz = event->size();
|
||||
const QSize hint = d_label->sizeHint();
|
||||
|
||||
d_label->setGeometry( 0, sz.height() - hint.height(),
|
||||
sz.width(), hint.height() );
|
||||
|
||||
const int knobHeight = d_knob->sizeHint().height();
|
||||
|
||||
int off = qCeil( d_knob->scaleDraw()->extent( d_knob->font() ) );
|
||||
off -= 15; // spacing
|
||||
|
||||
d_knob->setGeometry( 0, d_label->pos().y() - knobHeight + off,
|
||||
sz.width(), knobHeight );
|
||||
}
|
38
examples/oscilloscope/knob.h
Normal file
38
examples/oscilloscope/knob.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef _KNOB_H_
|
||||
#define _KNOB_H_
|
||||
|
||||
#include <qwidget.h>
|
||||
|
||||
class QwtKnob;
|
||||
class QLabel;
|
||||
|
||||
class Knob: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( QColor theme READ theme WRITE setTheme )
|
||||
|
||||
public:
|
||||
Knob( const QString &title,
|
||||
double min, double max, QWidget *parent = NULL );
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
void setValue( double value );
|
||||
double value() const;
|
||||
|
||||
void setTheme( const QColor & );
|
||||
QColor theme() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
double valueChanged( double );
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent( QResizeEvent * );
|
||||
|
||||
private:
|
||||
QwtKnob *d_knob;
|
||||
QLabel *d_label;
|
||||
};
|
||||
|
||||
#endif
|
36
examples/oscilloscope/main.cpp
Normal file
36
examples/oscilloscope/main.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <qapplication.h>
|
||||
#include "mainwindow.h"
|
||||
#include "samplingthread.h"
|
||||
|
||||
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() );
|
||||
samplingThread.setAmplitude( window.amplitude() );
|
||||
samplingThread.setInterval( window.signalInterval() );
|
||||
|
||||
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;
|
||||
}
|
69
examples/oscilloscope/mainwindow.cpp
Normal file
69
examples/oscilloscope/mainwindow.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include "mainwindow.h"
|
||||
#include "plot.h"
|
||||
#include "knob.h"
|
||||
#include "wheelbox.h"
|
||||
#include <qwt_scale_engine.h>
|
||||
#include <qlabel.h>
|
||||
#include <qlayout.h>
|
||||
|
||||
MainWindow::MainWindow( QWidget *parent ):
|
||||
QWidget( parent )
|
||||
{
|
||||
const double intervalLength = 10.0; // seconds
|
||||
|
||||
d_plot = new Plot( this );
|
||||
d_plot->setIntervalLength( intervalLength );
|
||||
|
||||
d_amplitudeKnob = new Knob( "Amplitude", 0.0, 200.0, this );
|
||||
d_amplitudeKnob->setValue( 160.0 );
|
||||
|
||||
d_frequencyKnob = new Knob( "Frequency [Hz]", 0.1, 20.0, this );
|
||||
d_frequencyKnob->setValue( 17.8 );
|
||||
|
||||
d_intervalWheel = new WheelBox( "Displayed [s]", 1.0, 100.0, 1.0, this );
|
||||
d_intervalWheel->setValue( intervalLength );
|
||||
|
||||
d_timerWheel = new WheelBox( "Sample Interval [ms]", 0.0, 20.0, 0.1, this );
|
||||
d_timerWheel->setValue( 10.0 );
|
||||
|
||||
QVBoxLayout* vLayout1 = new QVBoxLayout();
|
||||
vLayout1->addWidget( d_intervalWheel );
|
||||
vLayout1->addWidget( d_timerWheel );
|
||||
vLayout1->addStretch( 10 );
|
||||
vLayout1->addWidget( d_amplitudeKnob );
|
||||
vLayout1->addWidget( d_frequencyKnob );
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout( this );
|
||||
layout->addWidget( d_plot, 10 );
|
||||
layout->addLayout( vLayout1 );
|
||||
|
||||
connect( d_amplitudeKnob, SIGNAL( valueChanged( double ) ),
|
||||
SIGNAL( amplitudeChanged( double ) ) );
|
||||
connect( d_frequencyKnob, SIGNAL( valueChanged( double ) ),
|
||||
SIGNAL( frequencyChanged( double ) ) );
|
||||
connect( d_timerWheel, SIGNAL( valueChanged( double ) ),
|
||||
SIGNAL( signalIntervalChanged( double ) ) );
|
||||
|
||||
connect( d_intervalWheel, SIGNAL( valueChanged( double ) ),
|
||||
d_plot, SLOT( setIntervalLength( double ) ) );
|
||||
}
|
||||
|
||||
void MainWindow::start()
|
||||
{
|
||||
d_plot->start();
|
||||
}
|
||||
|
||||
double MainWindow::frequency() const
|
||||
{
|
||||
return d_frequencyKnob->value();
|
||||
}
|
||||
|
||||
double MainWindow::amplitude() const
|
||||
{
|
||||
return d_amplitudeKnob->value();
|
||||
}
|
||||
|
||||
double MainWindow::signalInterval() const
|
||||
{
|
||||
return d_timerWheel->value();
|
||||
}
|
32
examples/oscilloscope/mainwindow.h
Normal file
32
examples/oscilloscope/mainwindow.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <qwidget.h>
|
||||
|
||||
class Plot;
|
||||
class Knob;
|
||||
class WheelBox;
|
||||
|
||||
class MainWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow( QWidget * = NULL );
|
||||
|
||||
void start();
|
||||
|
||||
double amplitude() const;
|
||||
double frequency() const;
|
||||
double signalInterval() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void amplitudeChanged( double );
|
||||
void frequencyChanged( double );
|
||||
void signalIntervalChanged( double );
|
||||
|
||||
private:
|
||||
Knob *d_frequencyKnob;
|
||||
Knob *d_amplitudeKnob;
|
||||
WheelBox *d_timerWheel;
|
||||
WheelBox *d_intervalWheel;
|
||||
|
||||
Plot *d_plot;
|
||||
};
|
55
examples/oscilloscope/osci.css
Normal file
55
examples/oscilloscope/osci.css
Normal file
|
@ -0,0 +1,55 @@
|
|||
MainWindow
|
||||
{
|
||||
border: 1px solid white;
|
||||
border-radius: 20px;
|
||||
padding: 10px;
|
||||
background-color: qlineargradient( x1: 0, y1: 0, x2: 1, y2: 1,
|
||||
stop: 0 #31312C, stop: 0.5 #808080 stop: 1 #31312C );
|
||||
}
|
||||
|
||||
QwtPlotCanvas
|
||||
{
|
||||
border: 1px solid White;
|
||||
border-radius: 10px;
|
||||
background-color: #101010;
|
||||
color: yellow; /* used as curve color */
|
||||
}
|
||||
|
||||
QwtScaleWidget
|
||||
{
|
||||
color: white;
|
||||
}
|
||||
|
||||
WheelBox
|
||||
{
|
||||
qproperty-theme: #878787;
|
||||
}
|
||||
|
||||
QwtWheel
|
||||
{
|
||||
/* background-color: yellow; */
|
||||
qproperty-mass: 0.0;
|
||||
qproperty-tickCount: 5;
|
||||
qproperty-wheelWidth: 15;
|
||||
qproperty-borderWidth: 2;
|
||||
qproperty-wheelBorderWidth: 2;
|
||||
qproperty-wrapping: true;
|
||||
}
|
||||
|
||||
Knob
|
||||
{
|
||||
qproperty-theme: #606060;
|
||||
}
|
||||
|
||||
QwtKnob
|
||||
{
|
||||
qproperty-knobStyle: Sunken;
|
||||
qproperty-markerStyle: Nub;
|
||||
qproperty-markerSize: 8;
|
||||
qproperty-borderWidth: 2;
|
||||
}
|
||||
|
||||
QLCDNumber
|
||||
{
|
||||
color: yellow;
|
||||
}
|
31
examples/oscilloscope/oscilloscope.pro
Normal file
31
examples/oscilloscope/oscilloscope.pro
Normal file
|
@ -0,0 +1,31 @@
|
|||
################################################################
|
||||
# Qwt Widget Library
|
||||
# Copyright (C) 1997 Josef Wilgen
|
||||
# Copyright (C) 2002 Uwe Rathmann
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the Qwt License, Version 1.0
|
||||
################################################################
|
||||
|
||||
include( $${PWD}/../examples.pri )
|
||||
|
||||
TARGET = oscilloscope
|
||||
|
||||
HEADERS = \
|
||||
signaldata.h \
|
||||
plot.h \
|
||||
knob.h \
|
||||
wheelbox.h \
|
||||
samplingthread.h \
|
||||
curvedata.h \
|
||||
mainwindow.h
|
||||
|
||||
SOURCES = \
|
||||
signaldata.cpp \
|
||||
plot.cpp \
|
||||
knob.cpp \
|
||||
wheelbox.cpp \
|
||||
samplingthread.cpp \
|
||||
curvedata.cpp \
|
||||
mainwindow.cpp \
|
||||
main.cpp
|
254
examples/oscilloscope/plot.cpp
Normal file
254
examples/oscilloscope/plot.cpp
Normal file
|
@ -0,0 +1,254 @@
|
|||
#include "plot.h"
|
||||
#include "curvedata.h"
|
||||
#include "signaldata.h"
|
||||
#include <qwt_plot_grid.h>
|
||||
#include <qwt_plot_layout.h>
|
||||
#include <qwt_plot_canvas.h>
|
||||
#include <qwt_plot_marker.h>
|
||||
#include <qwt_plot_curve.h>
|
||||
#include <qwt_plot_directpainter.h>
|
||||
#include <qwt_curve_fitter.h>
|
||||
#include <qwt_painter.h>
|
||||
#include <qevent.h>
|
||||
|
||||
class Canvas: public QwtPlotCanvas
|
||||
{
|
||||
public:
|
||||
Canvas( QwtPlot *plot = NULL ):
|
||||
QwtPlotCanvas( plot )
|
||||
{
|
||||
// The backing store is important, when working with widget
|
||||
// overlays ( f.e rubberbands for zooming ).
|
||||
// Here we don't have them and the internal
|
||||
// backing store of QWidget is good enough.
|
||||
|
||||
setPaintAttribute( QwtPlotCanvas::BackingStore, false );
|
||||
setBorderRadius( 10 );
|
||||
|
||||
if ( QwtPainter::isX11GraphicsSystem() )
|
||||
{
|
||||
#if QT_VERSION < 0x050000
|
||||
// Even if not liked by the Qt development, Qt::WA_PaintOutsidePaintEvent
|
||||
// works on X11. This has a nice effect on the performance.
|
||||
|
||||
setAttribute( Qt::WA_PaintOutsidePaintEvent, true );
|
||||
#endif
|
||||
|
||||
// Disabling the backing store of Qt improves the performance
|
||||
// for the direct painter even more, but the canvas becomes
|
||||
// a native window of the window system, receiving paint events
|
||||
// for resize and expose operations. Those might be expensive
|
||||
// when there are many points and the backing store of
|
||||
// the canvas is disabled. So in this application
|
||||
// we better don't disable both backing stores.
|
||||
|
||||
if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) )
|
||||
{
|
||||
setAttribute( Qt::WA_PaintOnScreen, true );
|
||||
setAttribute( Qt::WA_NoSystemBackground, true );
|
||||
}
|
||||
}
|
||||
|
||||
setupPalette();
|
||||
}
|
||||
|
||||
private:
|
||||
void setupPalette()
|
||||
{
|
||||
QPalette pal = palette();
|
||||
|
||||
#if QT_VERSION >= 0x040400
|
||||
QLinearGradient gradient;
|
||||
gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
|
||||
gradient.setColorAt( 0.0, QColor( 0, 49, 110 ) );
|
||||
gradient.setColorAt( 1.0, QColor( 0, 87, 174 ) );
|
||||
|
||||
pal.setBrush( QPalette::Window, QBrush( gradient ) );
|
||||
#else
|
||||
pal.setBrush( QPalette::Window, QBrush( color ) );
|
||||
#endif
|
||||
|
||||
// QPalette::WindowText is used for the curve color
|
||||
pal.setColor( QPalette::WindowText, Qt::green );
|
||||
|
||||
setPalette( pal );
|
||||
}
|
||||
};
|
||||
|
||||
Plot::Plot( QWidget *parent ):
|
||||
QwtPlot( parent ),
|
||||
d_paintedPoints( 0 ),
|
||||
d_interval( 0.0, 10.0 ),
|
||||
d_timerId( -1 )
|
||||
{
|
||||
d_directPainter = new QwtPlotDirectPainter();
|
||||
|
||||
setAutoReplot( false );
|
||||
setCanvas( new Canvas() );
|
||||
|
||||
plotLayout()->setAlignCanvasToScales( true );
|
||||
|
||||
setAxisTitle( QwtPlot::xBottom, "Time [s]" );
|
||||
setAxisScale( QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue() );
|
||||
setAxisScale( QwtPlot::yLeft, -200.0, 200.0 );
|
||||
|
||||
QwtPlotGrid *grid = new QwtPlotGrid();
|
||||
grid->setPen( Qt::gray, 0.0, Qt::DotLine );
|
||||
grid->enableX( true );
|
||||
grid->enableXMin( true );
|
||||
grid->enableY( true );
|
||||
grid->enableYMin( false );
|
||||
grid->attach( this );
|
||||
|
||||
d_origin = new QwtPlotMarker();
|
||||
d_origin->setLineStyle( QwtPlotMarker::Cross );
|
||||
d_origin->setValue( d_interval.minValue() + d_interval.width() / 2.0, 0.0 );
|
||||
d_origin->setLinePen( Qt::gray, 0.0, Qt::DashLine );
|
||||
d_origin->attach( this );
|
||||
|
||||
d_curve = new QwtPlotCurve();
|
||||
d_curve->setStyle( QwtPlotCurve::Lines );
|
||||
d_curve->setPen( canvas()->palette().color( QPalette::WindowText ) );
|
||||
d_curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
|
||||
d_curve->setPaintAttribute( QwtPlotCurve::ClipPolygons, false );
|
||||
d_curve->setData( new CurveData() );
|
||||
d_curve->attach( this );
|
||||
}
|
||||
|
||||
Plot::~Plot()
|
||||
{
|
||||
delete d_directPainter;
|
||||
}
|
||||
|
||||
void Plot::start()
|
||||
{
|
||||
d_clock.start();
|
||||
d_timerId = startTimer( 10 );
|
||||
}
|
||||
|
||||
void Plot::replot()
|
||||
{
|
||||
CurveData *data = static_cast<CurveData *>( d_curve->data() );
|
||||
data->values().lock();
|
||||
|
||||
QwtPlot::replot();
|
||||
d_paintedPoints = data->size();
|
||||
|
||||
data->values().unlock();
|
||||
}
|
||||
|
||||
void Plot::setIntervalLength( double interval )
|
||||
{
|
||||
if ( interval > 0.0 && interval != d_interval.width() )
|
||||
{
|
||||
d_interval.setMaxValue( d_interval.minValue() + interval );
|
||||
setAxisScale( QwtPlot::xBottom,
|
||||
d_interval.minValue(), d_interval.maxValue() );
|
||||
|
||||
replot();
|
||||
}
|
||||
}
|
||||
|
||||
void Plot::updateCurve()
|
||||
{
|
||||
CurveData *data = static_cast<CurveData *>( d_curve->data() );
|
||||
data->values().lock();
|
||||
|
||||
const int numPoints = data->size();
|
||||
if ( numPoints > d_paintedPoints )
|
||||
{
|
||||
const bool doClip = !canvas()->testAttribute( Qt::WA_PaintOnScreen );
|
||||
if ( doClip )
|
||||
{
|
||||
/*
|
||||
Depending on the platform setting a clip might be an important
|
||||
performance issue. F.e. for Qt Embedded this reduces the
|
||||
part of the backing store that has to be copied out - maybe
|
||||
to an unaccelerated frame buffer device.
|
||||
*/
|
||||
|
||||
const QwtScaleMap xMap = canvasMap( d_curve->xAxis() );
|
||||
const QwtScaleMap yMap = canvasMap( d_curve->yAxis() );
|
||||
|
||||
QRectF br = qwtBoundingRect( *data,
|
||||
d_paintedPoints - 1, numPoints - 1 );
|
||||
|
||||
const QRect clipRect = QwtScaleMap::transform( xMap, yMap, br ).toRect();
|
||||
d_directPainter->setClipRegion( clipRect );
|
||||
}
|
||||
|
||||
d_directPainter->drawSeries( d_curve,
|
||||
d_paintedPoints - 1, numPoints - 1 );
|
||||
d_paintedPoints = numPoints;
|
||||
}
|
||||
|
||||
data->values().unlock();
|
||||
}
|
||||
|
||||
void Plot::incrementInterval()
|
||||
{
|
||||
d_interval = QwtInterval( d_interval.maxValue(),
|
||||
d_interval.maxValue() + d_interval.width() );
|
||||
|
||||
CurveData *data = static_cast<CurveData *>( d_curve->data() );
|
||||
data->values().clearStaleValues( d_interval.minValue() );
|
||||
|
||||
// To avoid, that the grid is jumping, we disable
|
||||
// the autocalculation of the ticks and shift them
|
||||
// manually instead.
|
||||
|
||||
QwtScaleDiv scaleDiv = axisScaleDiv( QwtPlot::xBottom );
|
||||
scaleDiv.setInterval( d_interval );
|
||||
|
||||
for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
|
||||
{
|
||||
QList<double> ticks = scaleDiv.ticks( i );
|
||||
for ( int j = 0; j < ticks.size(); j++ )
|
||||
ticks[j] += d_interval.width();
|
||||
scaleDiv.setTicks( i, ticks );
|
||||
}
|
||||
setAxisScaleDiv( QwtPlot::xBottom, scaleDiv );
|
||||
|
||||
d_origin->setValue( d_interval.minValue() + d_interval.width() / 2.0, 0.0 );
|
||||
|
||||
d_paintedPoints = 0;
|
||||
replot();
|
||||
}
|
||||
|
||||
void Plot::timerEvent( QTimerEvent *event )
|
||||
{
|
||||
if ( event->timerId() == d_timerId )
|
||||
{
|
||||
updateCurve();
|
||||
|
||||
const double elapsed = d_clock.elapsed() / 1000.0;
|
||||
if ( elapsed > d_interval.maxValue() )
|
||||
incrementInterval();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QwtPlot::timerEvent( event );
|
||||
}
|
||||
|
||||
void Plot::resizeEvent( QResizeEvent *event )
|
||||
{
|
||||
d_directPainter->reset();
|
||||
QwtPlot::resizeEvent( event );
|
||||
}
|
||||
|
||||
void Plot::showEvent( QShowEvent * )
|
||||
{
|
||||
replot();
|
||||
}
|
||||
|
||||
bool Plot::eventFilter( QObject *object, QEvent *event )
|
||||
{
|
||||
if ( object == canvas() &&
|
||||
event->type() == QEvent::PaletteChange )
|
||||
{
|
||||
d_curve->setPen( canvas()->palette().color( QPalette::WindowText ) );
|
||||
}
|
||||
|
||||
return QwtPlot::eventFilter( object, event );
|
||||
}
|
44
examples/oscilloscope/plot.h
Normal file
44
examples/oscilloscope/plot.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <qwt_plot.h>
|
||||
#include <qwt_interval.h>
|
||||
#include <qwt_system_clock.h>
|
||||
|
||||
class QwtPlotCurve;
|
||||
class QwtPlotMarker;
|
||||
class QwtPlotDirectPainter;
|
||||
|
||||
class Plot: public QwtPlot
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Plot( QWidget * = NULL );
|
||||
virtual ~Plot();
|
||||
|
||||
void start();
|
||||
virtual void replot();
|
||||
|
||||
virtual bool eventFilter( QObject *, QEvent * );
|
||||
|
||||
public Q_SLOTS:
|
||||
void setIntervalLength( double );
|
||||
|
||||
protected:
|
||||
virtual void showEvent( QShowEvent * );
|
||||
virtual void resizeEvent( QResizeEvent * );
|
||||
virtual void timerEvent( QTimerEvent * );
|
||||
|
||||
private:
|
||||
void updateCurve();
|
||||
void incrementInterval();
|
||||
|
||||
QwtPlotMarker *d_origin;
|
||||
QwtPlotCurve *d_curve;
|
||||
int d_paintedPoints;
|
||||
|
||||
QwtPlotDirectPainter *d_directPainter;
|
||||
|
||||
QwtInterval d_interval;
|
||||
int d_timerId;
|
||||
|
||||
QwtSystemClock d_clock;
|
||||
};
|
54
examples/oscilloscope/samplingthread.cpp
Normal file
54
examples/oscilloscope/samplingthread.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "samplingthread.h"
|
||||
#include "signaldata.h"
|
||||
#include <qwt_math.h>
|
||||
#include <math.h>
|
||||
|
||||
#if QT_VERSION < 0x040600
|
||||
#define qFastSin(x) ::sin(x)
|
||||
#endif
|
||||
|
||||
SamplingThread::SamplingThread( QObject *parent ):
|
||||
QwtSamplingThread( parent ),
|
||||
d_frequency( 5.0 ),
|
||||
d_amplitude( 20.0 )
|
||||
{
|
||||
}
|
||||
|
||||
void SamplingThread::setFrequency( double frequency )
|
||||
{
|
||||
d_frequency = frequency;
|
||||
}
|
||||
|
||||
double SamplingThread::frequency() const
|
||||
{
|
||||
return d_frequency;
|
||||
}
|
||||
|
||||
void SamplingThread::setAmplitude( double amplitude )
|
||||
{
|
||||
d_amplitude = amplitude;
|
||||
}
|
||||
|
||||
double SamplingThread::amplitude() const
|
||||
{
|
||||
return d_amplitude;
|
||||
}
|
||||
|
||||
void SamplingThread::sample( double elapsed )
|
||||
{
|
||||
if ( d_frequency > 0.0 )
|
||||
{
|
||||
const QPointF s( elapsed, value( elapsed ) );
|
||||
SignalData::instance().append( s );
|
||||
}
|
||||
}
|
||||
|
||||
double SamplingThread::value( double timeStamp ) const
|
||||
{
|
||||
const double period = 1.0 / d_frequency;
|
||||
|
||||
const double x = ::fmod( timeStamp, period );
|
||||
const double v = d_amplitude * qFastSin( x / period * 2 * M_PI );
|
||||
|
||||
return v;
|
||||
}
|
25
examples/oscilloscope/samplingthread.h
Normal file
25
examples/oscilloscope/samplingthread.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include <qwt_sampling_thread.h>
|
||||
|
||||
class SamplingThread: public QwtSamplingThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SamplingThread( QObject *parent = NULL );
|
||||
|
||||
double frequency() const;
|
||||
double amplitude() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setAmplitude( double );
|
||||
void setFrequency( double );
|
||||
|
||||
protected:
|
||||
virtual void sample( double elapsed );
|
||||
|
||||
private:
|
||||
virtual double value( double timeStamp ) const;
|
||||
|
||||
double d_frequency;
|
||||
double d_amplitude;
|
||||
};
|
133
examples/oscilloscope/signaldata.cpp
Normal file
133
examples/oscilloscope/signaldata.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
#include "signaldata.h"
|
||||
#include <qvector.h>
|
||||
#include <qmutex.h>
|
||||
#include <qreadwritelock.h>
|
||||
|
||||
class SignalData::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
boundingRect( 1.0, 1.0, -2.0, -2.0 ) // invalid
|
||||
{
|
||||
values.reserve( 1000 );
|
||||
}
|
||||
|
||||
inline void append( const QPointF &sample )
|
||||
{
|
||||
values.append( sample );
|
||||
|
||||
// adjust the bounding rectangle
|
||||
|
||||
if ( boundingRect.width() < 0 || boundingRect.height() < 0 )
|
||||
{
|
||||
boundingRect.setRect( sample.x(), sample.y(), 0.0, 0.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
boundingRect.setRight( sample.x() );
|
||||
|
||||
if ( sample.y() > boundingRect.bottom() )
|
||||
boundingRect.setBottom( sample.y() );
|
||||
|
||||
if ( sample.y() < boundingRect.top() )
|
||||
boundingRect.setTop( sample.y() );
|
||||
}
|
||||
}
|
||||
|
||||
QReadWriteLock lock;
|
||||
|
||||
QVector<QPointF> values;
|
||||
QRectF boundingRect;
|
||||
|
||||
QMutex mutex; // protecting pendingValues
|
||||
QVector<QPointF> pendingValues;
|
||||
};
|
||||
|
||||
SignalData::SignalData()
|
||||
{
|
||||
d_data = new PrivateData();
|
||||
}
|
||||
|
||||
SignalData::~SignalData()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
int SignalData::size() const
|
||||
{
|
||||
return d_data->values.size();
|
||||
}
|
||||
|
||||
QPointF SignalData::value( int index ) const
|
||||
{
|
||||
return d_data->values[index];
|
||||
}
|
||||
|
||||
QRectF SignalData::boundingRect() const
|
||||
{
|
||||
return d_data->boundingRect;
|
||||
}
|
||||
|
||||
void SignalData::lock()
|
||||
{
|
||||
d_data->lock.lockForRead();
|
||||
}
|
||||
|
||||
void SignalData::unlock()
|
||||
{
|
||||
d_data->lock.unlock();
|
||||
}
|
||||
|
||||
void SignalData::append( const QPointF &sample )
|
||||
{
|
||||
d_data->mutex.lock();
|
||||
d_data->pendingValues += sample;
|
||||
|
||||
const bool isLocked = d_data->lock.tryLockForWrite();
|
||||
if ( isLocked )
|
||||
{
|
||||
const int numValues = d_data->pendingValues.size();
|
||||
const QPointF *pendingValues = d_data->pendingValues.data();
|
||||
|
||||
for ( int i = 0; i < numValues; i++ )
|
||||
d_data->append( pendingValues[i] );
|
||||
|
||||
d_data->pendingValues.clear();
|
||||
|
||||
d_data->lock.unlock();
|
||||
}
|
||||
|
||||
d_data->mutex.unlock();
|
||||
}
|
||||
|
||||
void SignalData::clearStaleValues( double limit )
|
||||
{
|
||||
d_data->lock.lockForWrite();
|
||||
|
||||
d_data->boundingRect = QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid
|
||||
|
||||
const QVector<QPointF> values = d_data->values;
|
||||
d_data->values.clear();
|
||||
d_data->values.reserve( values.size() );
|
||||
|
||||
int index;
|
||||
for ( index = values.size() - 1; index >= 0; index-- )
|
||||
{
|
||||
if ( values[index].x() < limit )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( index > 0 )
|
||||
d_data->append( values[index++] );
|
||||
|
||||
while ( index < values.size() - 1 )
|
||||
d_data->append( values[index++] );
|
||||
|
||||
d_data->lock.unlock();
|
||||
}
|
||||
|
||||
SignalData &SignalData::instance()
|
||||
{
|
||||
static SignalData valueVector;
|
||||
return valueVector;
|
||||
}
|
33
examples/oscilloscope/signaldata.h
Normal file
33
examples/oscilloscope/signaldata.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef _SIGNAL_DATA_H_
|
||||
#define _SIGNAL_DATA_H_ 1
|
||||
|
||||
#include <qrect.h>
|
||||
|
||||
class SignalData
|
||||
{
|
||||
public:
|
||||
static SignalData &instance();
|
||||
|
||||
void append( const QPointF &pos );
|
||||
void clearStaleValues( double min );
|
||||
|
||||
int size() const;
|
||||
QPointF value( int index ) const;
|
||||
|
||||
QRectF boundingRect() const;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
SignalData();
|
||||
SignalData( const SignalData & );
|
||||
SignalData &operator=( const SignalData & );
|
||||
|
||||
virtual ~SignalData();
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
102
examples/oscilloscope/wheelbox.cpp
Normal file
102
examples/oscilloscope/wheelbox.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
#include "wheelbox.h"
|
||||
#include <qwt_wheel.h>
|
||||
#include <qlcdnumber.h>
|
||||
#include <qlabel.h>
|
||||
#include <qlayout.h>
|
||||
#include <qevent.h>
|
||||
#include <qapplication.h>
|
||||
|
||||
class Wheel: public QwtWheel
|
||||
{
|
||||
public:
|
||||
Wheel( WheelBox *parent ):
|
||||
QwtWheel( parent )
|
||||
{
|
||||
setFocusPolicy( Qt::WheelFocus );
|
||||
parent->installEventFilter( this );
|
||||
}
|
||||
|
||||
virtual bool eventFilter( QObject *object, QEvent *event )
|
||||
{
|
||||
if ( event->type() == QEvent::Wheel )
|
||||
{
|
||||
const QWheelEvent *we = static_cast<QWheelEvent *>( event );
|
||||
|
||||
QWheelEvent wheelEvent( QPoint( 5, 5 ), we->delta(),
|
||||
we->buttons(), we->modifiers(),
|
||||
we->orientation() );
|
||||
|
||||
QApplication::sendEvent( this, &wheelEvent );
|
||||
return true;
|
||||
}
|
||||
return QwtWheel::eventFilter( object, event );
|
||||
}
|
||||
};
|
||||
|
||||
WheelBox::WheelBox( const QString &title,
|
||||
double min, double max, double stepSize, QWidget *parent ):
|
||||
QWidget( parent )
|
||||
{
|
||||
|
||||
d_number = new QLCDNumber( this );
|
||||
d_number->setSegmentStyle( QLCDNumber::Filled );
|
||||
d_number->setAutoFillBackground( true );
|
||||
d_number->setFixedHeight( d_number->sizeHint().height() * 2 );
|
||||
d_number->setFocusPolicy( Qt::WheelFocus );
|
||||
|
||||
QPalette pal( Qt::black );
|
||||
pal.setColor( QPalette::WindowText, Qt::green );
|
||||
d_number->setPalette( pal );
|
||||
|
||||
d_wheel = new Wheel( this );
|
||||
d_wheel->setOrientation( Qt::Vertical );
|
||||
d_wheel->setInverted( true );
|
||||
d_wheel->setRange( min, max );
|
||||
d_wheel->setSingleStep( stepSize );
|
||||
d_wheel->setPageStepCount( 5 );
|
||||
d_wheel->setFixedHeight( d_number->height() );
|
||||
|
||||
d_number->setFocusProxy( d_wheel );
|
||||
|
||||
QFont font( "Helvetica", 10 );
|
||||
font.setBold( true );
|
||||
|
||||
d_label = new QLabel( title, this );
|
||||
d_label->setFont( font );
|
||||
|
||||
QHBoxLayout *hLayout = new QHBoxLayout;
|
||||
hLayout->setContentsMargins( 0, 0, 0, 0 );
|
||||
hLayout->setSpacing( 2 );
|
||||
hLayout->addWidget( d_number, 10 );
|
||||
hLayout->addWidget( d_wheel );
|
||||
|
||||
QVBoxLayout *vLayout = new QVBoxLayout( this );
|
||||
vLayout->addLayout( hLayout, 10 );
|
||||
vLayout->addWidget( d_label, 0, Qt::AlignTop | Qt::AlignHCenter );
|
||||
|
||||
connect( d_wheel, SIGNAL( valueChanged( double ) ),
|
||||
d_number, SLOT( display( double ) ) );
|
||||
connect( d_wheel, SIGNAL( valueChanged( double ) ),
|
||||
this, SIGNAL( valueChanged( double ) ) );
|
||||
}
|
||||
|
||||
void WheelBox::setTheme( const QColor &color )
|
||||
{
|
||||
d_wheel->setPalette( color );
|
||||
}
|
||||
|
||||
QColor WheelBox::theme() const
|
||||
{
|
||||
return d_wheel->palette().color( QPalette::Window );
|
||||
}
|
||||
|
||||
void WheelBox::setValue( double value )
|
||||
{
|
||||
d_wheel->setValue( value );
|
||||
d_number->display( value );
|
||||
}
|
||||
|
||||
double WheelBox::value() const
|
||||
{
|
||||
return d_wheel->value();
|
||||
}
|
40
examples/oscilloscope/wheelbox.h
Normal file
40
examples/oscilloscope/wheelbox.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef _WHEELBOX_H_
|
||||
#define _WHEELBOX_H_
|
||||
|
||||
#include <qwidget.h>
|
||||
|
||||
class QwtWheel;
|
||||
class QLabel;
|
||||
class QLCDNumber;
|
||||
|
||||
class WheelBox: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QColor theme READ theme WRITE setTheme )
|
||||
|
||||
public:
|
||||
WheelBox( const QString &title,
|
||||
double min, double max, double stepSize,
|
||||
QWidget *parent = NULL );
|
||||
|
||||
void setTheme( const QColor & );
|
||||
QColor theme() const;
|
||||
|
||||
void setUnit( const QString & );
|
||||
QString unit() const;
|
||||
|
||||
void setValue( double value );
|
||||
double value() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
double valueChanged( double );
|
||||
|
||||
private:
|
||||
QLCDNumber *d_number;
|
||||
QwtWheel *d_wheel;
|
||||
QLabel *d_label;
|
||||
|
||||
QString d_unit;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue