PDA

View Full Version : QwtPlotPicker Subclass Segfaults



npotts
5th December 2014, 18:34
I am trying to subclass QwtPlotPicker to change the default value for the displayed text, and everything I am doing causes segfaults. I have spent a couple hours at this with no avail. I am using latest Qwt from SVN (6.x series).


My QwtPlotPicker subclass .h:


class FreqdBmPicker : public QwtPlotPicker {
public:
FreqdBmPicker( QWidget *canvas );
private:
virtual QwtText trackerTextF( const QPointF &pos ) const;
};


My QwtPlotPicker subclass .cpp:


FreqdBmPicker::FreqdBmPicker( QWidget *canvas ): QwtPlotPicker( canvas ) {
setTrackerMode( QwtPicker::AlwaysOn );
setRubberBand( QwtPlotPicker::CrossRubberBand );
setStateMachine( new QwtPickerTrackerMachine() );
setTrackerPen(QColor(Qt::cyan));
setRubberBandPen(QColor(Qt::cyan));
}
QwtText FreqdBmPicker::trackerTextF( const QPointF &pos ) const {
QString rtn;
switch ( (int) std::log10(pos.x())) {
case 9: rtn = QString("(%1GHz, %2dBm)").arg(pos.x()/1e9, 0, 'f', 2).arg(pos.y(), 0, 'f', 1); break;
case 8:
case 7:
case 6: rtn = QString("(%1MHz, %2dBm)").arg(pos.x()/1e6, 0, 'f', 2).arg(pos.y(), 0, 'f', 1); break;
case 5:
case 4:
case 3: rtn = QString("(%1kHz, %2dBm)").arg(pos.x()/1e3, 0, 'f', 2).arg(pos.y(), 0, 'f', 1); break;
case 2:
case 1:
case 0: rtn = QString("(%1Hz, %2dBm)").arg(pos.x(), 0, 'f', 2).arg(pos.y(), 0, 'f', 1); break;
}
return QwtText(rtn);
}


In the calling *.cpp class:


canvas = new QwtPlotCanvas();
canvas->setPalette( Qt::black );
canvas->setBorderRadius(0);
plot->setCanvas(canvas);
TimeFreqPicker *pkr = new TimeFreqPicker(plot->canvas());


It appears to run, but the minute I click anywhere on the plot, it immediately segfaults. gdb backtrace:


#0 0x00007ffff6ffe26c in QwtPicker::adjustedPoints(QPolygon const&) const () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#1 0x00007ffff6fffb20 in QwtPicker::updateDisplay() () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#2 0x00007ffff6ffec76 in QwtPicker::eventFilter(QObject*, QEvent*) () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#3 0x00007ffff754a9e5 in QCoreApplicationPrivate::sendThroughObjectEventFil ters(QObject*, QEvent*) () from /usr/lib64/libQt5Core.so.5
#4 0x00007ffff78e843c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
#5 0x00007ffff78ed470 in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
#6 0x00007ffff754a7a5 in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib64/libQt5Core.so.5
#7 0x00007ffff7920295 in QWidgetPrivate::setGeometry_sys(int, int, int, int, bool) () from /usr/lib64/libQt5Widgets.so.5
#8 0x00007ffff7920f89 in QWidget::setGeometry(QRect const&) () from /usr/lib64/libQt5Widgets.so.5
#9 0x00007ffff7031334 in QwtPlot::updateLayout() () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#10 0x00007ffff7034491 in QwtPlot::event(QEvent*) () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#11 0x00007ffff78e845c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
#12 0x00007ffff78ed470 in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
#13 0x00007ffff754a7a5 in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib64/libQt5Core.so.5
#14 0x00007ffff754c63f in QCoreApplicationPrivate::sendPostedEvents(QObject* , int, QThreadData*) () from /usr/lib64/libQt5Core.so.5
#15 0x00007ffff7031d02 in QwtPlot::replot() () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#16 0x00007ffff7065fd1 in QwtPlotZoomer::zoom(QRectF const&) () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#17 0x00007ffff7066581 in QwtPlotZoomer::end(bool) () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#18 0x00007ffff700128a in QwtPicker::transition(QEvent const*) () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#19 0x00007ffff6ffec01 in QwtPicker::eventFilter(QObject*, QEvent*) () from /home/nickp/code/SpectralSignalHound-Viewer/qwt/lib/libqwt.so.6
#20 0x00007ffff754a9e5 in QCoreApplicationPrivate::sendThroughObjectEventFil ters(QObject*, QEvent*) () from /usr/lib64/libQt5Core.so.5
#21 0x00007ffff78e843c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
#22 0x00007ffff78edda6 in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
....


What am I doing wrong?

Uwe
6th December 2014, 10:27
The stack indicates a crash starting with a QwtPlotZoomer - how the code you have shown related to this ?

Uwe

npotts
7th December 2014, 01:02
Hm.. That is a bit wierd. Ok, not sure why I missed that earlier. I removed all the zoomer code, it no longer sefgaults, but now there are NO markers. I am expecting a horizontal and vertical bars to follow the mouse around on the screen with some custom text. Again:


QwtPlotPicker .cpp and .h


class FreqdBmPicker : public QwtPlotPicker {
public:
FreqdBmPicker( QWidget *canvas );
FreqdBmPicker(int xAxis, int yAxis, RubberBand rubberBand, DisplayMode trackerMode, QWidget* canvas);
virtual QwtText trackerTextF( const QPointF & ) const;
};



QwtText TimeScaleDraw::label(double v) const { //Convert Double date to a string
return QwtText(QDateTime::fromMSecsSinceEpoch((qint64) (v*1000)).toString("yyyy-MM-dd\nHH:mm:ss.zzz"));
}

FreqdBmPicker::FreqdBmPicker(int x, int y, RubberBand rb, DisplayMode dm, QWidget* w): QwtPlotPicker(x, y, rb, dm, w) {
setTrackerMode( dm );
setRubberBand( rb );
setStateMachine( new QwtPickerTrackerMachine() );
setTrackerPen(QColor(Qt::cyan));
setRubberBandPen(QColor(Qt::cyan));
qDebug() << isEnabled();
setEnabled(true);
}
FreqdBmPicker::FreqdBmPicker( QWidget *canvas ): QwtPlotPicker( canvas ) {
setTrackerMode( QwtPicker::AlwaysOn );
setRubberBand( QwtPlotPicker::CrossRubberBand );
setStateMachine( new QwtPickerTrackerMachine() );
setTrackerPen(QColor(Qt::cyan));
setRubberBandPen(QColor(Qt::cyan));
qDebug() << isEnabled();
setEnabled(true);
}
QwtText FreqdBmPicker::trackerTextF( const QPointF &pos ) const {
QString rtn;
switch ( (int) std::log10(pos.x())) {
case 9: rtn = QString("(%1GHz, %2dBm)").arg(pos.x()/1e9, 0, 'f', 2); break;
case 8:
case 7:
case 6: rtn = QString("(%1MHz, %2dBm)").arg(pos.x()/1e6, 0, 'f', 2); break;
case 5:
case 4:
case 3: rtn = QString("(%1kHz, %2dBm)").arg(pos.x()/1e3, 0, 'f', 2); break;
case 2:
case 1:
case 0:
default: rtn = QString("(%1Hz, %2dBm)").arg(pos.x(), 0, 'f', 2); break;
}
rtn = rtn.arg(pos.y(), 0, 'f', 1);
return QwtText(rtn);
}


Initialization and calling code. loadSweep() is called multiple times over the lifetime of the application


SweepInspector::SweepInspector(QWidget *parent) : QWidget(parent), data(NULL), d_curve(NULL), picker(NULL) {
setupUi(this);
plot->setObjectName( "SweepData" );
plot->setTitle( "RF Sweep" );
plot->setAxisTitle( QwtPlot::xBottom, "Frequency");
plot->setAxisTitle( QwtPlot::yLeft, QString( "Power Level (dBm)"));
plot->setAutoReplot(true);

plot->enableAxis(QwtPlot::xBottom, true);
plot->enableAxis(QwtPlot::yLeft, true);
plot->enableAxis(QwtPlot::xTop, false);
plot->enableAxis(QwtPlot::yRight, false);

canvas = new QwtPlotCanvas();
canvas->setPalette( Qt::black );
canvas->setBorderRadius(0);
plot->setCanvas(canvas);

//Allow zooming / panning
// zoomer = new QwtPlotZoomer( canvas );
// zoomer->setRubberBandPen( QColor( Qt::white ) );
// zoomer->setTrackerPen( QColor( Qt::white ) );
panner = new QwtPlotPanner( canvas );
panner->setMouseButton( Qt::MidButton );

picker = new FreqdBmPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, canvas);


//Setup grid
grid = new QwtPlotGrid();
grid->enableXMin( true );
grid->enableYMin( true );
QColor color(Qt::gray); color.setAlpha(128);
grid->setMajorPen( color, 1, Qt::DotLine );
grid->setMinorPen( color, 1, Qt::DotLine );
grid->attach( plot );

//format in kHz, MHz, GHz, not raw values
plot->setAxisScaleDraw(QwtPlot::xBottom, new FreqScaleDraw);

//connects
connect(timeIndex, SIGNAL(valueChanged(int)), this, SLOT(loadSweep(int)));
connect(timeIndex, SIGNAL(sliderMoved(int)), this, SLOT(sliderMoved(int)));
}

void SweepInspector::loadSweep(int index) {
//load in new sweep values from data
if (data == NULL) return;

//remove old data and get new
if (d_curve) d_curve->attach(NULL);
plot->detachItems();
fsweep sweep = data->getSweep(index);

d_curve = new QwtPlotCurve( timestamp->text() ); //Qwt will delete() this when its done with it
d_curve->setRenderHint( QwtPlotItem::RenderAntialiased );
d_curve->setStyle( QwtPlotCurve::Lines );
d_curve->setPen( QColor( Qt::yellow ), 2, Qt::SolidLine );
d_curve->setSamples( sweep );
d_curve->attach(plot);

delete(picker);
picker = new FreqdBmPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, canvas);
connect(picker, SIGNAL(selected(QPointF)), this, SLOT(moved(QPointF)));

QwtInterval frange = data->limits(FREQ);
plot->setAxisScale(QwtPlot::xBottom, frange.minValue(), frange.maxValue(), (frange.maxValue() - frange.minValue())/ 5.0);
plot->setAxisScale(QwtPlot::yLeft, -135, 20, 10.0);
plot->setTitle( QString("RF Sweep @ %1").arg(timestamp->text()) );
//set maximum zoom out
// zoomer->setZoomBase(QRectF(QPointF(frange.minValue(), 20), QPointF(frange.maxValue(), -135)));
// zoomer->zoomBase();
plot->replot();
plot->repaint();
}

Uwe
7th December 2014, 09:28
A lot of code, but what is your question ?

Uwe

npotts
7th December 2014, 16:59
Haha, trees from the Forrest....


Essentially, my QwtPlotPickers are not appearing on the plots, and the format functions are never called.