void Plot::setTransformation( QwtTransform *transform ) { QwtLinearScaleEngine *scaleEngine = new QwtLinearScaleEngine(); scaleEngine->setTransformation( transform ); setAxisScaleEngine( QwtPlot::xBottom, scaleEngine ); // we have to reassign the axis settinge, because they are // invalidated, when the scale engine has changed QwtScaleDiv scaleDiv = axisScaleEngine( QwtPlot::xBottom )->divideScale( 10.0, 1000.0, 8, 10 ); QList<double> ticks; ticks += 10.0; ticks += scaleDiv.ticks( QwtScaleDiv::MajorTick ); scaleDiv.setTicks( QwtScaleDiv::MajorTick, ticks ); setAxisScaleDiv( QwtPlot::xBottom, scaleDiv ); replot(); }
/*! \brief Paint the plot into a given rectangle. Paint the contents of a QwtPlot instance into a given rectangle. \param painter Painter \param plotRect Bounding rectangle \param pfilter Print filter \sa QwtPlotPrintFilter */ void QwtPlot::print(QPainter *painter, const QRect &plotRect, const QwtPlotPrintFilter &pfilter) const { int axisId; if ( painter == 0 || !painter->isActive() || !plotRect.isValid() || size().isNull() ) return; painter->save(); #if 1 /* PDF: In Qt4 ( <= 4.3.2 ) the scales are painted in gray instead of black. See http://trolltech.com/developer/task-tracker/index_html?id=184671&method=entry The dummy lines below work around the problem. */ const QPen pen = painter->pen(); painter->setPen(QPen(Qt::black, 1)); painter->setPen(pen); #endif // All paint operations need to be scaled according to // the paint device metrics. QwtPainter::setMetricsMap(this, painter->device()); const QwtMetricsMap &metricsMap = QwtPainter::metricsMap(); // It is almost impossible to integrate into the Qt layout // framework, when using different fonts for printing // and screen. To avoid writing different and Qt unconform // layout engines we change the widget attributes, print and // reset the widget attributes again. This way we produce a lot of // useless layout events ... pfilter.apply((QwtPlot *)this); int baseLineDists[QwtPlot::axisCnt]; if ( pfilter.options() & QwtPlotPrintFilter::PrintFrameWithScales ) { for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if ( scaleWidget ) { baseLineDists[axisId] = scaleWidget->margin(); scaleWidget->setMargin(0); } } } // Calculate the layout for the print. int layoutOptions = QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) ) layoutOptions |= QwtPlotLayout::IgnoreMargin; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) ) layoutOptions |= QwtPlotLayout::IgnoreLegend; ((QwtPlot *)this)->plotLayout()->activate(this, QwtPainter::metricsMap().deviceToLayout(plotRect), layoutOptions); if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle) && (!titleLabel()->text().isEmpty())) { printTitle(painter, plotLayout()->titleRect()); } if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend) && legend() && !legend()->isEmpty() ) { printLegend(painter, plotLayout()->legendRect()); } for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if (scaleWidget) { int baseDist = scaleWidget->margin(); int startDist, endDist; scaleWidget->getBorderDistHint(startDist, endDist); printScale(painter, axisId, startDist, endDist, baseDist, plotLayout()->scaleRect(axisId)); } } QRect canvasRect = plotLayout()->canvasRect(); /* The border of the bounding rect needs to ba scaled to layout coordinates, so that it is aligned to the axes */ QRect boundingRect( canvasRect.left() - 1, canvasRect.top() - 1, canvasRect.width() + 2, canvasRect.height() + 2); boundingRect = metricsMap.layoutToDevice(boundingRect); boundingRect.setWidth(boundingRect.width() - 1); boundingRect.setHeight(boundingRect.height() - 1); canvasRect = metricsMap.layoutToDevice(canvasRect); // When using QwtPainter all sizes where computed in pixel // coordinates and scaled by QwtPainter later. This limits // the precision to screen resolution. A better solution // is to scale the maps and print in unlimited resolution. QwtScaleMap map[axisCnt]; for (axisId = 0; axisId < axisCnt; axisId++) { map[axisId].setTransformation(axisScaleEngine(axisId)->transformation()); const QwtScaleDiv &scaleDiv = *axisScaleDiv(axisId); map[axisId].setScaleInterval(scaleDiv.lBound(), scaleDiv.hBound()); double from, to; if ( axisEnabled(axisId) ) { const int sDist = axisWidget(axisId)->startBorderDist(); const int eDist = axisWidget(axisId)->endBorderDist(); const QRect &scaleRect = plotLayout()->scaleRect(axisId); if ( axisId == xTop || axisId == xBottom ) { from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist); to = metricsMap.layoutToDeviceX(scaleRect.right() + 1 - eDist); } else { from = metricsMap.layoutToDeviceY(scaleRect.bottom() + 1 - eDist ); to = metricsMap.layoutToDeviceY(scaleRect.top() + sDist); } } else { int margin = plotLayout()->canvasMargin(axisId); if ( axisId == yLeft || axisId == yRight ) { margin = metricsMap.layoutToDeviceY(margin); from = canvasRect.bottom() - margin; to = canvasRect.top() + margin; } else { margin = metricsMap.layoutToDeviceX(margin); from = canvasRect.left() + margin; to = canvasRect.right() - margin; } } map[axisId].setPaintXInterval(from, to); } // The canvas maps are already scaled. QwtPainter::setMetricsMap(painter->device(), painter->device()); printCanvas(painter, boundingRect, canvasRect, map, pfilter); QwtPainter::resetMetricsMap(); ((QwtPlot *)this)->plotLayout()->invalidate(); // reset all widgets with their original attributes. if ( pfilter.options() & QwtPlotPrintFilter::PrintFrameWithScales ) { // restore the previous base line dists for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if ( scaleWidget ) scaleWidget->setMargin(baseLineDists[axisId]); } } pfilter.reset((QwtPlot *)this); painter->restore(); }
/** * Set the scale of the horizontal axis * @param from :: Minimum value * @param to :: Maximum value */ void OneCurvePlot::setXScale(double from, double to) { QFontMetrics fm(axisFont(QwtPlot::xBottom)); int n = from != 0.0 ? abs(static_cast<int>(floor(log10(fabs(from))))) : 0; int n1 = to != 0.0 ? abs(static_cast<int>(floor(log10(fabs(to))))) : 0; if (n1 > n) n = n1; n += 4; // approxiamte width of a tick label in pixels int labelWidth = n * fm.width("0"); // calculate number of major ticks int nMajorTicks = this->width() / labelWidth; if ( nMajorTicks > 6 ) nMajorTicks = 6; // try creating a scale const QwtScaleDiv div = axisScaleEngine(QwtPlot::xBottom)->divideScale(from,to,nMajorTicks,nMajorTicks); // Major ticks are placed at round numbers so the first or last tick could be missing making // scale look ugly. Trying to fix it if possible bool rescaled = false; // get actual tick positions const QwtValueList& ticks = div.ticks(QwtScaleDiv::MajorTick); if (!ticks.empty() && ticks.size() < nMajorTicks) { // how much first tick is shifted from the lower bound double firstShift = ticks.front() - div.lBound(); // how much last tick is shifted from the upper bound double lastShift = div.hBound() - ticks.back(); // range of the scale double range = fabs(div.hBound() - div.lBound()); // we say that 1st tick is missing if first tick is father away from its end of the scale // than the last tick is from its end bool isFirstMissing = fabs(firstShift) > fabs(lastShift) ; // if first tick is missing if (isFirstMissing) { // distance between nearest major ticks double tickSize = 0; if (ticks.size() == 1) { // guess the tick size in case of only one visible double tickLog = log10(firstShift); tickLog = tickLog > 0 ? ceil(tickLog) : floor(tickLog); tickSize = pow(10.,tickLog); } else if (ticks.size() > 1) { // take the difference between the two first ticks tickSize = ticks[1] - ticks[0]; } // claculate how much lower bound must be moved to make the missing tick visible double shift = (ticks.front() - tickSize) - from; // if the shift is not very big rescale the axis if (fabs(shift/range) < 0.1) { from += shift; const QwtScaleDiv updatedDiv = axisScaleEngine(QwtPlot::xBottom)->divideScale(from,to,nMajorTicks,nMajorTicks); setAxisScaleDiv(xBottom,updatedDiv); rescaled = true; } } else // last tick is missing { // distance between nearest major ticks double tickSize = 0; if (ticks.size() == 1) { // guess the tick size in case of only one visible double tickLog = log10(lastShift); tickLog = tickLog > 0 ? ceil(tickLog) : floor(tickLog); tickSize = pow(10.,tickLog); } else if (ticks.size() > 1) { // take the difference between the two first ticks tickSize = ticks[1] - ticks[0]; } // claculate how much upper bound must be moved to make the missing tick visible double shift = (ticks.back() + tickSize) - to; // if the shift is not very big rescale the axis if (fabs(shift/range) < 0.1) { to += shift; const QwtScaleDiv updatedDiv = axisScaleEngine(QwtPlot::xBottom)->divideScale(from,to,nMajorTicks,nMajorTicks); setAxisScaleDiv(xBottom,updatedDiv); rescaled = true; } } } if (!rescaled) { setAxisScaleDiv(xBottom,div); } m_zoomer->setZoomBase(); }
/*! \brief Paint the plot into a given rectangle. Paint the contents of a QwtPlot instance into a given rectangle. \param painter Painter \param plotRect Bounding rectangle \param pfilter Print filter \sa QwtPlotPrintFilter */ void QwtPlot::print(QPainter *painter, const QRect &plotRect, const QwtPlotPrintFilter &pfilter) const { int axisId; if ( painter == 0 || !painter->isActive() || !plotRect.isValid() || size().isNull() ) return; painter->save(); // All paint operations need to be scaled according to // the paint device metrics. QwtPainter::setMetricsMap(this, painter->device()); const QwtMetricsMap &metricsMap = QwtPainter::metricsMap(); // It is almost impossible to integrate into the Qt layout // framework, when using different fonts for printing // and screen. To avoid writing different and Qt unconform // layout engines we change the widget attributes, print and // reset the widget attributes again. This way we produce a lot of // useless layout events ... pfilter.apply((QwtPlot *)this); int baseLineDists[QwtPlot::axisCnt]; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) ) { // In case of no background we set the backbone of // the scale on the frame of the canvas. for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if ( scaleWidget ) { baseLineDists[axisId] = scaleWidget->baseLineDist(); scaleWidget->setBaselineDist(0); } } } // Calculate the layout for the print. int layoutOptions = QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) ) layoutOptions |= QwtPlotLayout::IgnoreMargin; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) ) layoutOptions |= QwtPlotLayout::IgnoreLegend; ((QwtPlot *)this)->plotLayout()->activate(this, QwtPainter::metricsMap().deviceToLayout(plotRect), layoutOptions); if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle) && (!titleLabel()->text().isEmpty())) { printTitle(painter, plotLayout()->titleRect()); } if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend) && legend() && !legend()->isEmpty() ) { printLegend(painter, plotLayout()->legendRect()); } for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if (scaleWidget) { int baseDist = scaleWidget->baseLineDist(); int startDist, endDist; scaleWidget->getBorderDistHint(startDist, endDist); printScale(painter, axisId, startDist, endDist, baseDist, plotLayout()->scaleRect(axisId)); } } const QRect canvasRect = metricsMap.layoutToDevice(plotLayout()->canvasRect()); // When using QwtPainter all sizes where computed in pixel // coordinates and scaled by QwtPainter later. This limits // the precision to screen resolution. A much better solution // is to scale the maps and print in unlimited resolution. QwtArray<QwtScaleMap> map(axisCnt); for (axisId = 0; axisId < axisCnt; axisId++) { map[axisId].setTransformation(axisScaleEngine(axisId)->transformation()); const QwtScaleDiv &scaleDiv = *axisScaleDiv(axisId); map[axisId].setScaleInterval(scaleDiv.lBound(), scaleDiv.hBound()); double from, to; if ( axisEnabled(axisId) ) { const int sDist = axisWidget(axisId)->startBorderDist(); const int eDist = axisWidget(axisId)->endBorderDist(); const QRect &scaleRect = plotLayout()->scaleRect(axisId); if ( axisId == xTop || axisId == xBottom ) { from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist); to = metricsMap.layoutToDeviceX(scaleRect.right() - eDist); } else { from = metricsMap.layoutToDeviceY(scaleRect.bottom() - sDist); to = metricsMap.layoutToDeviceY(scaleRect.top() + eDist); } } else { const int margin = plotLayout()->canvasMargin(axisId); const QRect &canvasRect = plotLayout()->canvasRect(); if ( axisId == yLeft || axisId == yRight ) { from = metricsMap.layoutToDeviceX(canvasRect.bottom() - margin); to = metricsMap.layoutToDeviceX(canvasRect.top() + margin); } else { from = metricsMap.layoutToDeviceY(canvasRect.left() + margin); to = metricsMap.layoutToDeviceY(canvasRect.right() - margin); } } map[axisId].setPaintXInterval(from, to); } // The canvas maps are already scaled. QwtPainter::setMetricsMap(painter->device(), painter->device()); printCanvas(painter, canvasRect, map, pfilter); QwtPainter::resetMetricsMap(); ((QwtPlot *)this)->plotLayout()->invalidate(); // reset all widgets with their original attributes. if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) ) { // restore the previous base line dists for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if ( scaleWidget ) scaleWidget->setBaselineDist(baseLineDists[axisId]); } } pfilter.reset((QwtPlot *)this); painter->restore(); }
Psdplot::Psdplot(QWidget *parent) :QwtPlot(parent) ,xMin_(0) ,xMax_(0) ,haveLine1_(false) ,haveLine2_(false) ,havevLine1_(false) { counter_ = 0; numPoints_ = 1; indexPoints_ = new double[numPoints_]; dataPoints_ = new double[numPoints_]; setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QPalette palette; palette.setColor(canvas()->backgroundRole(), QColor("white")); canvas()->setPalette(palette); curve_ = new QwtPlotCurve("Curve"); curve_->setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); curve_->setStyle(QwtPlotCurve::Lines); curve_->setRawSamples(indexPoints_, dataPoints_, numPoints_); curve_->setYAxis(QwtPlot::yLeft); curve_->attach(this); memset(dataPoints_, 0x0, numPoints_*sizeof(double)); for(int i=0;i<numPoints_;i++) indexPoints_[i] = i; line1_ = new QwtPlotCurve("Line1"); line1_->setPen(QPen(Qt::red, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); line1_->setStyle(QwtPlotCurve::Lines); line1_->attach(this); line2_ = new QwtPlotCurve("Line2"); line2_->setPen(QPen(Qt::blue, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); line2_->setStyle(QwtPlotCurve::Lines); line2_->attach(this); vline1_ = new QwtPlotCurve("vLine1"); vline1_->setPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); vline1_->setStyle(QwtPlotCurve::Lines); vline1_->attach(this); enableAxis(QwtPlot::yRight); QwtScaleWidget *leftAxis = axisWidget(QwtPlot::yLeft); connect(leftAxis, SIGNAL(scaleDivChanged()), this, SLOT(linkScales())); setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine); setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine); setAxisScaleEngine(QwtPlot::yRight, new QwtLinearScaleEngine); axisScaleEngine(QwtPlot::xBottom)->setAttribute(QwtScaleEngine::Floating,true); axisScaleEngine(QwtPlot::yLeft)->setAttribute(QwtScaleEngine::Floating,true); axisScaleEngine(QwtPlot::yRight)->setAttribute(QwtScaleEngine::Floating,true); zoomer_ = new MyZoomer(canvas()); zoomer_->setMousePattern(QwtEventPattern::MouseSelect1, Qt::LeftButton); zoomer_->setMousePattern(QwtEventPattern::MouseSelect2, Qt::LeftButton, Qt::ControlModifier); panner_ = new QwtPlotPanner(canvas()); panner_->setMouseButton(Qt::RightButton); magnifier_ = new QwtPlotMagnifier(canvas()); magnifier_->setMouseButton(Qt::NoButton); }