/*! Update the axes scales \param intervals Scale intervals */ void QwtPlotRescaler::updateScales( QwtInterval intervals[QwtPlot::axisCnt] ) const { if ( d_data->inReplot >= 5 ) { return; } QwtPlot *plt = const_cast<QwtPlot *>( plot() ); const bool doReplot = plt->autoReplot(); plt->setAutoReplot( false ); for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { if ( axis == referenceAxis() || aspectRatio( axis ) > 0.0 ) { double v1 = intervals[axis].minValue(); double v2 = intervals[axis].maxValue(); if ( plt->axisScaleDiv( axis )->lowerBound() > plt->axisScaleDiv( axis )->upperBound() ) { qSwap( v1, v2 ); } if ( d_data->inReplot >= 1 ) { d_data->axisData[axis].scaleDiv = *plt->axisScaleDiv( axis ); } if ( d_data->inReplot >= 2 ) { QList<double> ticks[QwtScaleDiv::NTickTypes]; for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) ticks[i] = d_data->axisData[axis].scaleDiv.ticks( i ); plt->setAxisScaleDiv( axis, QwtScaleDiv( v1, v2, ticks ) ); } else { plt->setAxisScale( axis, v1, v2 ); } } } const bool immediatePaint = plt->canvas()->testPaintAttribute( QwtPlotCanvas::ImmediatePaint ); plt->canvas()->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, false ); plt->setAutoReplot( doReplot ); d_data->inReplot++; plt->replot(); d_data->inReplot--; plt->canvas()->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, immediatePaint ); }
/** Plot class contructor. */ AmplitudePlot::AmplitudePlot(QWidget* parent) : QWidget(parent), _ui(new Ui::AmplitudePlotForm) { _ui->setupUi(this); QwtPlot* p = _ui->plot; p->setCanvasBackground(QColor(Qt::white)); // We don't need the cache here p->canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); p->canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false); // Axis p->setAxisTitle(QwtPlot::xBottom, "Ticks"); p->setAxisTitle(QwtPlot::yLeft, "Height"); QwtPlotPicker* picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::PointSelection | QwtPicker::DragSelection, QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, p->canvas()); picker->setRubberBandPen(QColor(Qt::darkGreen)); picker->setRubberBand(QwtPicker::CrossRubberBand); picker->setTrackerPen(QColor(Qt::darkGreen)); }
static void renderItem( QPainter *painter, QwtPlotAbstractSeriesItem *seriesItem, int from, int to ) { QwtPlot *plot = seriesItem->plot(); const QwtScaleMap xMap = plot->canvasMap( seriesItem->xAxis() ); const QwtScaleMap yMap = plot->canvasMap( seriesItem->yAxis() ); painter->setRenderHint( QPainter::Antialiasing, seriesItem->testRenderHint( QwtPlotItem::RenderAntialiased ) ); seriesItem->drawSeries( painter, xMap, yMap, plot->canvas()->contentsRect(), from, to ); }
void Editor::setEnabled( bool on ) { if ( on == d_isEnabled ) return; QwtPlot *plot = qobject_cast<QwtPlot *>( parent() ); if ( plot ) { d_isEnabled = on; if ( on ) { plot->canvas()->installEventFilter( this ); } else { plot->canvas()->removeEventFilter( this ); delete d_overlay; d_overlay = NULL; } } }
// Получение геометрии индикации масштабирования шкалы QRect *QAxisZoomSvc::axisZoomRect(QPoint evpos,int ax) { // получаем указатель на график QwtPlot *plt = zoom->plot(); // определяем (для удобства) геометрию QRect gc = plt->canvas()->geometry(); // канвы графика QRect gw = plt->axisWidget(ax)->geometry(); // и виджета шкалы // определяем текущее положение курсора относительно канвы графика int x = evpos.x() + gw.x() - gc.x() - scb_pxl; int y = evpos.y() + gw.y() - gc.y() - scb_pyt; // запоминаем (для удобства) int wax = gw.width(); // ширину виджета шкалы int hax = gw.height(); // и высоту // читаем режим масштабирования QwtChartZoom::QConvType ct = zoom->regim(); // объявляем положение левого верхнего угла, int wl,wt,ww,wh; // ширину и высоту // если масштабируется горизонтальная шкала, то if (ax == QwtPlot::xBottom || ax == QwtPlot::xTop) { // если изменяется правая граница, то if (ct == QwtChartZoom::ctAxisHR) { // ограничение на положение курсора слева int mn = floor((float)(scb_pw/16)); // если курсор слишком близко к левой границе, то if (x < mn) x = mn; // ширина прямоугольника ww = floor((float)(x * scb_pw / scp_x)); // применяем ограничения ww = limitSize(ww,scb_pw); // левый отступ прямоугольника wl = sab_pxl; } else // иначе (изменяется левая граница) { // ограничение на положение курсора справа int mx = floor((float)(15*scb_pw/16)); // если курсор слишком близко к правой границе, то if (x > mx) x = mx; // ширина прямоугольника ww = floor((float)((scb_pw - x) * scb_pw / (scb_pw - scp_x))); // применяем ограничения ww = limitSize(ww,scb_pw); // левый отступ прямоугольника wl = sab_pxl + scb_pw - ww; } // высота прямоугольника wh = 4; // верхний отступ прямоугольника wt = 10; // для нижней шкалы // если не помещается на шкале, корректируем if (wt + wh > hax) wt = hax - wh; // для верхней шкалы симметрично if (ax == QwtPlot::xTop) wt = hax - wt - wh; } else // иначе (масштабируется вертикальная шкала) { // если изменяется нижняя граница, то if (ct == QwtChartZoom::ctAxisVB) { // ограничение на положение курсора сверху int mn = floor((float)(scb_ph/16)); // если курсор слишком близко к верхней границе, то if (y < mn) y = mn; // высота прямоугольника wh = floor((float)(y * scb_ph / scp_y)); // применяем ограничения wh = limitSize(wh,scb_ph); // верхний отступ прямоугольника wt = sab_pyt; } else // иначе (изменяется верхняя граница) { // ограничение на положение курсора снизу int mx = floor((float)(15*scb_ph/16)); // если курсор слишком близко к нижней границе, то if (y > mx) y = mx; // высота прямоугольника wh = floor((float)((scb_ph - y) * scb_ph / (scb_ph - scp_y))); // применяем ограничения wh = limitSize(wh,scb_ph); // верхний отступ прямоугольника = смещению курсора wt = sab_pyt + scb_ph - wh; } // ширина прямоугольника ww = 4; // верхний отступ прямоугольника wl = 10; // для правой шкалы // если не помещается на шкале, корректируем if (wl + ww > wax) wl = wax - ww; // для левой шкалы симметрично if (ax == QwtPlot::yLeft) wl = wax - wl - ww; } // создаем и возвращаем геометрию виджета // с вычисленными размерами return new QRect(wl,wt,ww,wh); }
// Обработчик нажатия на кнопку мыши над шкалой // (включение изменения масштаба шкалы) void QAxisZoomSvc::startAxisZoom(QMouseEvent *mEvent,int ax) { // фиксируем исходные границы графика (если этого еще не было сделано) zoom->fixBounds(); // если в данный момент еще не включен ни один из режимов if (zoom->regim() == QwtChartZoom::ctNone) { // если нажата левая кнопка мыши, то // включаем один из режимов масштабирования if (mEvent->button() == Qt::LeftButton) { // получаем указатели на QwtPlot *plt = zoom->plot(); // график QwtScaleWidget *sw = plt->axisWidget(ax); // виджет шкалы // получаем карту основной горизонтальной шкалы QwtScaleMap sm = plt->canvasMap(zoom->masterH()); // для того чтобы фиксировать начальные левую и правую границы scb_xl = sm.s1(); scb_xr = sm.s2(); scb_wx = sm.sDist(); // аналогично получаем карту основной вертикальной шкалы sm = plt->canvasMap(zoom->masterV()); // для того чтобы фиксировать начальные нижнюю и верхнюю границы scb_yb = sm.s1(); scb_yt = sm.s2(); scb_hy = sm.sDist(); // определяем (для удобства) геометрию QRect gc = plt->canvas()->geometry(); // канвы графика QRect gw = sw->geometry(); // и виджета шкалы // текущее левое смещение графика (в пикселах относительно канвы) scb_pxl = plt->transform(zoom->masterH(),scb_xl); // текущая ширина графика (в пикселах) scb_pw = plt->transform(zoom->masterH(),scb_xr) - scb_pxl; // текущее левое смещение графика // (в пикселах относительно виджета шкалы) sab_pxl = scb_pxl + gc.x() - gw.x(); // текущее верхнее смещение графика (в пикселах относительно канвы) scb_pyt = plt->transform(zoom->masterV(),scb_yt); // текущая высота графика (в пикселах) scb_ph = plt->transform(zoom->masterV(),scb_yb) - scb_pyt; // текущее верхнее смещение графика // (в пикселах относительно виджета шкалы) sab_pyt = scb_pyt + gc.y() - gw.y(); // запоминаем текущее положение курсора относительно канвы // (за вычетом смещений графика) scp_x = mEvent->pos().x() - sab_pxl; scp_y = mEvent->pos().y() - sab_pyt; // если масштабируется горизонтальная шкала if (ax == QwtPlot::xBottom || ax == QwtPlot::xTop) { // если левая граница меньше правой, if (scb_wx > 0) // если ширина канвы больше минимума, if (scb_pw > 36) { // в зависимости от положения курсора // (правее или левее середины шкалы) // включаем соответствующий режим - изменение if (scp_x >= floor((float)(scb_pw/2))) zoom->setRegim(QwtChartZoom::ctAxisHR); // правой границы else zoom->setRegim(QwtChartZoom::ctAxisHL); // или левой } } else // иначе (масштабируется вертикальная шкала) { // если нижняя граница меньше верхней, if (scb_hy > 0) // если высота канвы больше минимума, if (scb_ph > 18) { // в зависимости от положения курсора // (ниже или выше середины шкалы) // включаем соответствующий режим - изменение if (scp_y >= floor((float)(scb_ph/2))) zoom->setRegim(QwtChartZoom::ctAxisVB); // нижней границы else zoom->setRegim(QwtChartZoom::ctAxisVT); // или верхней } } // если один из режимов был включен if (zoom->regim() != QwtChartZoom::ctNone) { // запоминаем текущий курсор tCursor = sw->cursor(); // устанавливаем курсор PointingHand sw->setCursor(Qt::PointingHandCursor); // если легкий режим и включена индикация, то if (light && indiAxZ) { // создаем виджет, индицирующий масштабирование шкалы zwid = new QWidget(plt->axisWidget(ax)); // назначаем ему цвет zwid->setStyleSheet(QString( "background-color:rgb(%1,%2,%3);").arg( awClr.red()).arg(awClr.green()).arg(awClr.blue())); // и прорисовываем showZoomWidget(mEvent->pos(),ax); } } } } }
// Применение результатов перемещения границы шкалы void QAxisZoomSvc::axisApplyMove(QPoint evpos,int ax) { // получаем указатель на график QwtPlot *plt = zoom->plot(); // определяем (для удобства) геометрию QRect gc = plt->canvas()->geometry(); // канвы графика QRect gw = plt->axisWidget(ax)->geometry(); // и виджета шкалы // определяем текущее положение курсора относительно канвы // (за вычетом смещений графика) int x = evpos.x() + gw.x() - gc.x() - scb_pxl; int y = evpos.y() + gw.y() - gc.y() - scb_pyt; bool bndCh = false; // пока ничего не изменилось // читаем режим масштабирования QwtChartZoom::QConvType ct = zoom->regim(); // в зависимости от включенного режима выполняем некоторые действия switch (ct) { // режим изменения левой границы case QwtChartZoom::ctAxisHL: { // ограничение на положение курсора справа if (x >= scb_pw) x = scb_pw-1; // вычисляем новую ширину шкалы double wx = scb_wx * (scb_pw - scp_x) / (scb_pw - x); // применяем ограничения wx = limitScale(wx,scb_wx); // вычисляем новую левую границу double xl = scb_xr - wx; // устанавливаем ее для горизонтальной шкалы zoom->isb_x->set(xl,scb_xr); bndCh = true; // изменилась граница break; } // режим изменения правой границы case QwtChartZoom::ctAxisHR: { // ограничение на положение курсора слева if (x <= 0) x = 1; // вычисляем новую ширину шкалы double wx = scb_wx * scp_x / x; // применяем ограничения wx = limitScale(wx,scb_wx); // вычисляем новую правую границу double xr = scb_xl + wx; // устанавливаем ее для горизонтальной шкалы zoom->isb_x->set(scb_xl,xr); bndCh = true; // изменилась граница break; } // режим изменения нижней границы case QwtChartZoom::ctAxisVB: { // ограничение на положение курсора сверху if (y <= 0) y = 1; // вычисляем новую высоту шкалы double hy = scb_hy * scp_y / y; // применяем ограничения hy = limitScale(hy,scb_hy); // вычисляем новую нижнюю границу double yb = scb_yt - hy; // устанавливаем ее для вертикальной шкалы zoom->isb_y->set(yb,scb_yt); bndCh = true; // изменилась граница break; } // режим изменения верхней границы case QwtChartZoom::ctAxisVT: { // ограничение на положение курсора снизу if (y >= scb_ph) y = scb_ph-1; // вычисляем новую высоту шкалы double hy = scb_hy * (scb_ph - scp_y) / (scb_ph - y); // применяем ограничения hy = limitScale(hy,scb_hy); // вычисляем новую верхнюю границу double yt = scb_yb + hy; // устанавливаем ее для вертикальной шкалы zoom->isb_y->set(scb_yb,yt); bndCh = true; // изменилась граница break; } // для прочих режимов ничего не делаем default: ; } // если какя-либо граница изменилась, то перестраиваем график if (bndCh) plt->replot(); }
bool Editor::eventFilter( QObject* object, QEvent* event ) { QwtPlot *plot = qobject_cast<QwtPlot *>( parent() ); if ( plot && object == plot->canvas() ) { switch( event->type() ) { case QEvent::MouseButtonPress: { const QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent* >( event ); if ( d_overlay == NULL && mouseEvent->button() == Qt::LeftButton ) { const bool accepted = pressed( mouseEvent->pos() ); if ( accepted ) { d_overlay = new Overlay( plot->canvas(), this ); d_overlay->updateOverlay(); d_overlay->show(); } } break; } case QEvent::MouseMove: { if ( d_overlay ) { const QMouseEvent* mouseEvent = dynamic_cast< QMouseEvent* >( event ); const bool accepted = moved( mouseEvent->pos() ); if ( accepted ) d_overlay->updateOverlay(); } break; } case QEvent::MouseButtonRelease: { const QMouseEvent* mouseEvent = static_cast<QMouseEvent* >( event ); if ( d_overlay && mouseEvent->button() == Qt::LeftButton ) { released( mouseEvent->pos() ); delete d_overlay; d_overlay = NULL; } break; } default: break; } return false; } return QObject::eventFilter( object, event ); }
void PlotExporter::exportPlot(QwtPlot *plot, const QRectF &zoom) { QSizeF guessedDimensions; ExportPlotToImageDialog::Parameters p = m_exportDlg->parameters(); m_exportDlg->setAspectRatio(plot->size().width() / plot->size().height()); while (m_exportDlg->exec() == QDialog::Accepted) { p = m_exportDlg->parameters(); QString path; if (p.path.length() < 0) { QMessageBox::warning(nullptr, QObject::tr("Invalid input"), QObject::tr("Invalid path")); continue; } if (!m_supportedFormats.contains(p.format)) { QMessageBox::warning(nullptr, QObject::tr("Invalid input"), QObject::tr("Invalid output format")); continue; } if (p.path.endsWith("." + p.format)) path = p.path; else path = p.path + "." + p.format; /* Create a temporary QwtPlot to use to write the chart to file */ QwtPlot exPlot; QwtPlotZoomer exPlorZoomer(exPlot.canvas()); exPlorZoomer.zoom(zoom); exPlot.setCanvasBackground(QBrush(Qt::white)); exPlot.setTitle(p.title); exPlot.setAxisTitle(QwtPlot::xBottom, plot->axisTitle(QwtPlot::xBottom)); exPlot.setAxisTitle(QwtPlot::xTop, plot->axisTitle(QwtPlot::xTop)); exPlot.setAxisTitle(QwtPlot::yLeft, plot->axisTitle(QwtPlot::yLeft)); exPlot.setAxisTitle(QwtPlot::yRight, plot->axisTitle(QwtPlot::yRight)); QwtPlotItemList curves = plot->itemList(); /* Attach all plots from the GUI plot to the temporary plot * Note that this will detach the plots from the GUI plot! */ QList<qreal> curvePenWidths; for (QwtPlotItem *i : curves) { QwtPlotCurve *c = dynamic_cast<QwtPlotCurve *>(i); if (c != nullptr) { QPen p = c->pen(); qreal w = p.widthF(); qreal nw; curvePenWidths.push_back(w); nw = w - 1.0; if (nw < 0.0) nw = 0.0; p.setWidthF(nw); c->setPen(p); } i->attach(&exPlot); } /* Scale up from millimeters to centimeters*/ QSizeF dimensionsMM(p.dimensions.width() * 10.0, p.dimensions.height() * 10.0); /* Store current properties of the plot as we need to change them for rendering */ QFont xBottomFont = plot->axisWidget(QwtPlot::xBottom)->font(); QFont xTopFont = plot->axisWidget(QwtPlot::xTop)->font(); QFont yLeftFont = plot->axisWidget(QwtPlot::yLeft)->font(); QFont yRightFont = plot->axisWidget(QwtPlot::yRight)->font(); QFont xBottomTitleFont = plot->axisTitle(QwtPlot::xBottom).font(); QFont xTopTitleFont = plot->axisTitle(QwtPlot::xTop).font(); QFont yLeftTitleFont = plot->axisTitle(QwtPlot::yLeft).font(); QFont yRightTitleFont = plot->axisTitle(QwtPlot::yRight).font(); QFont titleFont = plot->title().font(); const qreal xBottomPenWidth = plot->axisWidget(QwtPlot::xBottom)->scaleDraw()->penWidth() > 0 ? plot->axisWidget(QwtPlot::xBottom)->scaleDraw()->penWidth() : 1.0; const qreal xTopPenWidth = plot->axisWidget(QwtPlot::xTop)->scaleDraw()->penWidth() > 0 ? plot->axisWidget(QwtPlot::xTop)->scaleDraw()->penWidth() : 1.0; const qreal yLeftPenWidth = plot->axisWidget(QwtPlot::yLeft)->scaleDraw()->penWidth() > 0 ? plot->axisWidget(QwtPlot::yLeft)->scaleDraw()->penWidth() : 1.0; const qreal yRightPenWidth = plot->axisWidget(QwtPlot::yRight)->scaleDraw()->penWidth() > 0 ? plot->axisWidget(QwtPlot::yRight)->scaleDraw()->penWidth() : 1.0; /* Recalculate sizes by the DPI for every element that needs it */ const qreal outputInPixels = (static_cast<qreal>(p.dimensions.width()) / 2.54) * p.dpi; const qreal scalingRatio = (static_cast<qreal>(qApp->desktop()->logicalDpiX()) / p.dpi) * (outputInPixels / plot->geometry().width()); const qreal _xBottomPenWidth = floor((xBottomPenWidth * scalingRatio) + 0.45); const qreal _xTopPenWidth = floor((xTopPenWidth * scalingRatio) + 0.45); const qreal _yLeftPenWidth = floor((yLeftPenWidth * scalingRatio) + 0.45); const qreal _yRightPenWidth = floor((yRightPenWidth * scalingRatio) + 0.45); xBottomFont.setPointSizeF(p.axisNumbersFontSize * scalingRatio); xTopFont.setPointSizeF(p.axisNumbersFontSize * scalingRatio); yLeftFont.setPointSizeF(p.axisNumbersFontSize * scalingRatio); yRightFont.setPointSizeF(p.axisNumbersFontSize * scalingRatio); xBottomTitleFont.setPointSizeF(p.axisTitlesFontSize * scalingRatio); xTopTitleFont.setPointSizeF(p.axisTitlesFontSize * scalingRatio); yLeftTitleFont.setPointSizeF(p.axisTitlesFontSize * scalingRatio); yRightTitleFont.setPointSizeF(p.axisTitlesFontSize * scalingRatio); titleFont.setPointSizeF(p.chartTitleFontSize * scalingRatio); exPlot.axisWidget(QwtPlot::xBottom)->scaleDraw()->setPenWidth(_xBottomPenWidth); exPlot.axisWidget(QwtPlot::xTop)->scaleDraw()->setPenWidth(_xTopPenWidth); exPlot.axisWidget(QwtPlot::yLeft)->scaleDraw()->setPenWidth(_yLeftPenWidth); exPlot.axisWidget(QwtPlot::yRight)->scaleDraw()->setPenWidth(_yRightPenWidth); exPlot.setPalette(m_plotPalette); exPlot.axisWidget(QwtPlot::xBottom)->setPalette(m_plotPalette); exPlot.axisWidget(QwtPlot::xTop)->setPalette(m_plotPalette); exPlot.axisWidget(QwtPlot::yLeft)->setPalette(m_plotPalette); exPlot.axisWidget(QwtPlot::yRight)->setPalette(m_plotPalette); exPlot.axisWidget(QwtPlot::xBottom)->setFont(xBottomFont); exPlot.axisWidget(QwtPlot::xTop)->setFont(xTopFont); exPlot.axisWidget(QwtPlot::yLeft)->setFont(yLeftFont); exPlot.axisWidget(QwtPlot::yRight)->setFont(yRightFont); setAxisTitleFont(&exPlot, QwtPlot::xBottom, xBottomTitleFont); setAxisTitleFont(&exPlot, QwtPlot::xTop, xTopTitleFont); setAxisTitleFont(&exPlot, QwtPlot::yLeft, yLeftTitleFont); setAxisTitleFont(&exPlot, QwtPlot::yRight, yRightTitleFont); setTitleFont(&exPlot, titleFont); exPlot.replot(); renderPlotToFile(&exPlot, path, p.format, dimensionsMM, p.dpi); /* Reattach the plots back to the GUI plot */ for (QwtPlotItem *i : curves) { QwtPlotCurve *c = dynamic_cast<QwtPlotCurve *>(i); if (c != nullptr) { QPen p = c->pen(); if (curvePenWidths.isEmpty()) break; p.setWidthF(curvePenWidths.front()); curvePenWidths.pop_front(); c->setPen(p); } i->attach(plot); } break; /* Exit the while loop */ } }
dtkPlotViewZoomer::dtkPlotViewZoomer(dtkPlotView *parent) : QObject(parent) { QwtPlot *plot = reinterpret_cast<QwtPlot *>(parent->plotWidget()); d = new dtkPlotViewZoomerPrivate(reinterpret_cast<QwtPlotCanvas *>(plot->canvas())); }