Results 1 to 12 of 12

Thread: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

  1. #1
    Join Date
    Jun 2015
    Posts
    109
    Thanks
    20
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Question How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    Design:
    Here I have design a graph where I can plot some signals like oscilloscope. Now I need two vertical and two horizontal lines on the graph which can move vertically and horizontally and also show cross points(symbol) when any signals get cross this lines.

    Qt Code:
    1. PlotterWidget::PlotterWidget(QWidget *parent)
    2. : QGraphicsView( parent ),
    3. layout(new QVBoxLayout(this)), plot(new QwtPlot()), legend(new QwtLegend()),
    4. m_zoomP(new PlotZoomer(QwtPlot::xBottom, QwtPlot::yLeft, plot->canvas()))
    5. {
    6. layout->setAlignment(plot->canvas(), Qt::AlignTop);
    7. layout->setSizeConstraint(QLayout::SetDefaultConstraint);
    8. plot->setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum);
    9.  
    10.  
    11. layout->addWidget(plot);
    12.  
    13. plot->plotLayout()->setAlignCanvasToScales(true);//update on crossing the graph
    14.  
    15. m_zoomM[0] = new QwtPlotMagnifier(plot->canvas()); // ( void ) new QwtPlotMagnifier( canvas );
    16. m_zoomM[0]->setWheelModifiers(Qt::NoModifier); //Scroll --> Both Axis
    17.  
    18. m_zoomM[1] = new QwtPlotMagnifier(plot->canvas());
    19. m_zoomM[1]->setWheelModifiers(Qt::ControlModifier); //Ctrl + Scroll --> on X-axis
    20. m_zoomM[1]->setAxisEnabled(Qt::XAxis,false);
    21.  
    22.  
    23. QWidget *horizontalLineWidget = new QWidget(plot->canvas());
    24. horizontalLineWidget->setFixedHeight(2);
    25. horizontalLineWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    26. horizontalLineWidget->setStyleSheet(QString("background-color: #c0c0c0;"));
    27.  
    28. QwtPlotGrid *grid = new QwtPlotGrid();
    29. grid->setPen(QPen(Qt::gray, 0.0, Qt::SolidLine));
    30. grid->enableX(true);
    31. grid->enableXMin(true);
    32. grid->enableY(true);
    33. grid->enableYMin(true);
    34. grid->attach(plot);
    35.  
    36. legend->setDefaultItemMode(QwtLegendData::Checkable);
    37. QwtSymbol *sym=new QwtSymbol(QwtSymbol::Diamond,QBrush(Qt::red),QPen(Qt::red),QSize(5,5));
    38. d_marker1 = new QwtPlotMarker();
    39. d_marker1->setSymbol(sym);
    40. d_marker1->setLegendIconSize(QSize(20,30));
    41. d_marker1->setLabel(QwtText("VLine1"));
    42. d_marker1->setRenderHint(QwtPlotItem::RenderHint::RenderAntialiased);
    43. d_marker1->setTitle(QwtText("VLine1"));
    44. d_marker1->setLabelOrientation(Qt::Vertical);
    45. d_marker1->setValue(333, 0);
    46. d_marker1->setLineStyle(QwtPlotMarker::VLine);
    47. d_marker1->setLabelAlignment(Qt::AlignRight | Qt::AlignBottom);
    48. d_marker1->setLinePen(QPen(Qt::blue, 1, Qt::DashDotLine));
    49. d_marker1->setItemAttribute( QwtPlotItem::Legend, true);
    50.  
    51. d_marker1->attach(plot);
    52.  
    53. d_marker2 = new QwtPlotMarker();
    54. d_marker2->setSymbol(sym);
    55. d_marker2->setValue(0, 333);
    56. d_marker2->setLabel(QwtText("HLine1"));
    57. d_marker2->setLineStyle(QwtPlotMarker::HLine);
    58. d_marker2->setTitle(QwtText("HLine1"));
    59. d_marker2->setLabelAlignment(Qt::AlignRight | Qt::AlignBottom);
    60. d_marker2->setLinePen(QPen(Qt::blue, 1, Qt::DashDotLine));
    61. d_marker2->attach(plot);
    62.  
    63. d_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft,
    64. QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn,
    65. plot->canvas());
    66. d_picker1 = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft,
    67. QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn,
    68. plot->canvas());
    69.  
    70. d_picker->setStateMachine(new QwtPickerDragPointMachine);
    71. d_picker1->setStateMachine(new QwtPickerClickPointMachine);
    72.  
    73. d_picker->setRubberBandPen(QColor(Qt::green));
    74. d_picker->setTrackerPen(QColor(Qt::blue));
    75. d_picker->setEnabled(true);
    76.  
    77. connect(d_picker1, SIGNAL(selected(const QPointF &)),
    78. SLOT(selected(const QPointF &)));
    79.  
    80.  
    81. plot->setFocusProxy(plot->canvas());
    82. plot->setFocusPolicy(Qt::StrongFocus);
    83. plot->setFocus();
    84. plot->installEventFilter(this);
    85.  
    86.  
    87. plot->setAutoReplot(true);
    88. setScaleType("Auto");
    89.  
    90. plot->insertLegend(legend, QwtPlot::RightLegend );
    91. plot->replot();
    92.  
    93. connect( legend, SIGNAL( checked( const QVariant &, bool, int ) ), SLOT( &Input::legendChecked( const QVariant &, bool ) ) );
    94. }
    To copy to clipboard, switch view to plain text mode 

    And to pick the Line I have write below code

    Qt Code:
    1. void PlotterWidget::selected(const QPointF &pos)
    2. {
    3. qDebug()<<"selected";
    4. const QwtPlotItemList& items = plot->itemList();
    5.  
    6. QMetaObject MetaObject = this->staticMetaObject;
    7. QMetaEnum MetaEnum = MetaObject.enumerator(MetaObject.indexOfEnumerator("MarkLine"));
    8.  
    9. for ( QwtPlotItemIterator i = items.begin(); i != items.end(); ++i )
    10. {
    11. if ( (*i)->rtti() == QwtPlotItem::Rtti_PlotMarker )
    12. {
    13. m_mark = static_cast<QwtPlotMarker*>(*i);
    14. if(!m_mark->isVisible())
    15. {
    16. continue;
    17. }
    18. if (sqrt( pow( (m_mark->xValue() - pos.x()), 2 )) <= 5 || sqrt( pow( (m_mark->yValue() - pos.y()), 2 )) <=5)
    19. {
    20. setLineMarker(static_cast<MarkLine>(MetaEnum.keysToValue(m_mark->label().text().toLatin1())));
    21. switch(getLineMarker())
    22. {
    23. case VLine1:
    24. d_marker1->setLinePen(QPen(Qt::blue, 3, Qt::SolidLine));
    25. break;
    26. case HLine1:
    27. d_marker2->setLinePen(QPen(Qt::blue, 3, Qt::SolidLine));
    28. break;
    29. };
    30. connect(d_picker, SIGNAL(moved(const QPoint &)),
    31. SLOT(moved(const QPoint &)));
    32. }
    33. }
    34. }
    35. }
    To copy to clipboard, switch view to plain text mode 


    Problem:
    I can able to pick line on grid when its of size x(0-1000) and y(0-1000), but the problem is when I'm trying to zoom in/out too much then I cant able to pass this below IF statement properly, because the distance is too less to pick Line.
    Qt Code:
    1. if (sqrt( pow( (m_mark->xValue() - pos.x()), 2 )) <= 5 || sqrt( pow( (m_mark->yValue() - pos.y()), 2 )) <=5)
    To copy to clipboard, switch view to plain text mode 

    Need solution how to pick this line properly without affecting zooming the graph ?
    It is possible during Zooming, make QwtPlotMarker not get move along with the grid or not zoomed?
    And also while zooming, QwtPlotMarker Line get hidden somewhere and difficult to find, so how to deal with this ?

    I really get stuck in this, please show me the way.

    Thanks a lot for reading this post.

  2. #2
    Join Date
    Jun 2015
    Posts
    109
    Thanks
    20
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    I have added event filter which identify the wheel up/down and based on that I have manage to increase the 5 using setting variable m_pickPoint in the event and it work for normal condition.
    Qt Code:
    1. if (sqrt( pow( (m_mark->xValue() - pos.x()), 2 )) <= m_pickPoint || sqrt( pow( (m_mark->yValue() - pos.y()), 2 )) <=m_pickPoint )
    To copy to clipboard, switch view to plain text mode 

    So here I'm unable to understand at what factor I should increase or decrease the value m_pickPoint, so that the above logic work properly and pick the exact line.
    Qt Code:
    1. case QEvent::Wheel:
    2. QWheelEvent* we = static_cast<QWheelEvent*>(e);
    3. if(we->angleDelta().y()>0)
    4. {
    5. m_pickPoint = m_pickPoint + m_pickPoint*0.05;
    6. qDebug()<<"Position"<<m_pickPoint;
    7. }
    8. else
    9. {
    10. m_pickPoint = m_pickPoint - m_pickPoint*0.05;
    11. qDebug()<<"Negative"<<m_pickPoint;
    12. }
    To copy to clipboard, switch view to plain text mode 

    Please provide your solution, where as this above solution looks kind of dirty, so if their is some elegant solution then please suggest.
    Last edited by npatil15; 8th January 2019 at 12:32.

  3. #3
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    You have to translate the coordinates of your marker and the mouse click into widget coordinates. See https://qwt.sourceforge.io/class_qwt...3d2ce46507b865

    Uwe

  4. #4
    Join Date
    Jun 2015
    Posts
    109
    Thanks
    20
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    Hi,

    Thanks for the reply,

    I have no trouble while catching/translating exact coordinates on the plot/widget. The problem is when I zoom in/out, the IF logic doen't work properly because I cant handle the m_pickPoint, which help me get the closet area to pick the QwtPlotMarker line. So looking for a solution how do I pick a line with such solution which doesn't affect on zoom in/out.

    Or is their a easiest way, that I can create a line widget and simply do drag and drop event. I have tried the same but dont know how to handle it, because I just want to drag to vertically or horizontally only not other way.

  5. #5
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    The zoomer installs an event filter for the plot canvas to handle the mouse events. In general it is possible to install as many events filters as you like - they are processed in reverse order of how they have been installed until one of them returns true.
    So you can simply install your own event filter - or create a QwtPicker/QwtPlotPicker - after attaching the zoomer.

    Uwe

  6. #6
    Join Date
    Jun 2015
    Posts
    109
    Thanks
    20
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    I have implement the eventfilter attached to zoomer which detect mouseevent and using this I can drag and drop the line on the graph.
    Also based on the zoom level I have manipulate the QwtPlotPicker to pick the line properly. But the way I implement is not picking the line properly when the zoom level is too deep, so normally it works perfectly.

  7. #7
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    Quote Originally Posted by npatil15 View Post
    I have implement the eventfilter attached to zoomer ...
    I would create an extra QwtPlotPicker for this usecase, where you return false from it eventFilter, when you don't want to forward the event to the zoomer. But this is not necessary to solve your problem.

    But the way I implement is not picking the line properly when the zoom level is too deep, so normally it works perfectly.
    Here we are back to my previous hint. Translate point and marker position into widget coordinates - then you can use a fixed distance in pixels, regardless of the zoom level.

  8. The following user says thank you to Uwe for this useful post:

    npatil15 (10th January 2019)

  9. #8
    Join Date
    Jun 2015
    Posts
    109
    Thanks
    20
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    I got your point, and sure this will be the solution if I translate point and marker into widget coordinates.
    But as I'm new for qwt and not sure how to do that. Can you please give me some code snippets or any link which explains about it ?

  10. #9
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming


  11. #10
    Join Date
    Jun 2015
    Posts
    109
    Thanks
    20
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    Somehow I have tried with the mention solution, which transform point and marker into widget coordinates. And its working fine.
    Qt Code:
    1. if(sqrt( pow( (m_plot->transform(QwtPlot::xBottom, m_mark->xValue()) - m_plot->transform(QwtPlot::xBottom, pos.x())), 2 )) <= 5 || sqrt( pow( (m_plot->transform(QwtPlot::xBottom, m_mark->yValue()) - m_plot->transform(QwtPlot::xBottom, pos.y())), 2 )) <=5 )
    To copy to clipboard, switch view to plain text mode 

    Here I have two marker (in future it will be four). Before when I used m_mark->xValue() its always fixed until I drag to other position(regardless of zooming). And when I used m_plot->transform(QwtPlot::xBottom, m_mark->xValue()) its value get changes by simply zoom in/out which should not happen. How I can prevent it from changing its value on zooming ?


    Added after 54 minutes:


    Please have a look on below logic,

    Qt Code:
    1. void OscilloscopeWidget::selected(const QPointF &pos)
    2. {
    3. const QwtPlotItemList& items = m_plot->itemList();
    4.  
    5. QMetaObject MetaObject = this->staticMetaObject;
    6. QMetaEnum MetaEnum = MetaObject.enumerator(MetaObject.indexOfEnumerator("MarkLine"));
    7.  
    8. //m_zoomP->setEnabled(false);
    9. for ( QwtPlotItemIterator i = items.begin(); i != items.end(); ++i )
    10. {
    11. if ( (*i)->rtti() == QwtPlotItem::Rtti_PlotMarker )
    12. {
    13. QwtPlotMarker *m_mark = static_cast<QwtPlotMarker*>(*i);
    14.  
    15. qDebug()<<"Marker :"<<m_mark->label().text().toLatin1();
    16. qDebug()<<"X Values :"<<m_plot->transform(QwtPlot::xBottom, m_mark->xValue())<<m_plot->transform(QwtPlot::xBottom, pos.x());
    17. qDebug()<<"Y Values :"<<m_plot->transform(QwtPlot::xBottom, m_mark->yValue())<<m_plot->transform(QwtPlot::xBottom, pos.y());
    18.  
    19. if(!m_mark->isVisible())
    20. {
    21. continue;
    22. }
    23. if(sqrt( pow( (m_plot->transform(QwtPlot::xBottom, m_mark->xValue()) - m_plot->transform(QwtPlot::xBottom, pos.x())), 2 )) <= 5 || sqrt( pow( (m_plot->transform(QwtPlot::xBottom, m_mark->yValue()) - m_plot->transform(QwtPlot::xBottom, pos.y())), 2 )) <=5 )
    24. {
    25.  
    26. setLineMarker(static_cast<MarkLine>(MetaEnum.keysToValue(m_mark->label().text().toLatin1())));
    27. switch(getLineMarker())
    28. {
    29. case VLine1:
    30. m_line[0]->setLinePen(QPen(Qt::blue, 3, Qt::SolidLine));
    31. break;
    32. case HLine1:
    33. m_line[1]->setLinePen(QPen(Qt::blue, 3, Qt::SolidLine));
    34. break;
    35. }
    36. connect(m_picker[0], SIGNAL(moved(const QPoint &)), SLOT(moved(const QPoint &)));
    37. }
    38. }
    39. }
    40. }
    To copy to clipboard, switch view to plain text mode 

    Check the output of qDebug() as below,
    When I click on the plot/widget, it checks for all the QwtPlotMarker available in the widget. Currently I have two Marker, so the for loop checks for two times when I click ones and in the given output the 3rd and 5th line qDebug output is wrong and I dont know from where this values comes. Also this values are not fixed as on the zoom in/out it changes and cause conflicts on picking the line Marker. How I can prevent this value ?
    Qt Code:
    1. unknown(0)[19800]: Marker : "VLine1"
    2. unknown(0)[19800]: X Values : 138 155
    3. unknown(0)[19800]: Y Values : 2 327.813
    4. unknown(0)[19800]: Marker : "HLine1"
    5. unknown(0)[19800]: X Values : 2 155
    6. unknown(0)[19800]: Y Values : 15.26 327.813
    To copy to clipboard, switch view to plain text mode 
    Last edited by npatil15; 10th January 2019 at 10:12.

  12. #11
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    Before when I used m_mark->xValue() its always fixed until I drag to other position(regardless of zooming).
    Sure, plot coordinates are not affected by zooming. And when moving a marker to a different plot coordinate, the plot coordinate changes - kind of obvious.

    And when I used m_plot->transform(QwtPlot::xBottom, m_mark->xValue()) its value get changes by simply zoom in/out which should not happen. How I can prevent it from changing its value on zooming ?
    Widget coordinates are calculated by mapping plot coordinates according to the scales. When changing the scales the mapping changes and you end up with different widget coordinates. That's how it is.

    But what exactly is your question ?

    Uwe

  13. The following user says thank you to Uwe for this useful post:

    npatil15 (10th January 2019)

  14. #12
    Join Date
    Jun 2015
    Posts
    109
    Thanks
    20
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to pick line of QwtPlotMarker using QwtPlotPicker without affecting zooming

    Yes you right, after several debugging I found that what you said.
    I have used different logic which solved my problem, I'll mention here for information.
    Qt Code:
    1. if(sqrt( pow( (m_plot->transform(QwtPlot::xBottom, m_line[0]->xValue()) - m_plot->transform(QwtPlot::xBottom, pos.x())), 2 )) <= 5 )
    2. {
    3. qDebug()<<"Marker 1st IF :"<<m_mark->label().text().toLatin1();
    4. setLineMarker(static_cast<MarkLine>(MetaEnum.keysToValue(m_line[0]->label().text().toLatin1())));
    5. m_line[0]->setLinePen(QPen(Qt::blue, 3, Qt::SolidLine));
    6. connect(m_picker[0], SIGNAL(moved(const QPoint &)), SLOT(moved(const QPoint &)));
    7. break;
    8. }
    9. else if(sqrt( pow( (m_plot->transform(QwtPlot::xBottom, m_line[1]->yValue()) - m_plot->transform(QwtPlot::xBottom, pos.y())), 2 )) <=5)
    10. {
    11. qDebug()<<"Marker 2nd IF :"<<m_mark->label().text().toLatin1();
    12. setLineMarker(static_cast<MarkLine>(MetaEnum.keysToValue(m_line[1]->label().text().toLatin1())));
    13. m_line[1]->setLinePen(QPen(Qt::blue, 3, Qt::SolidLine));
    14. connect(m_picker[0], SIGNAL(moved(const QPoint &)), SLOT(moved(const QPoint &)));
    15. break;
    16. }
    To copy to clipboard, switch view to plain text mode 
    Here instead of using m_mark->xValue() I have used directly my defined marker position m_line[0]->xValue(). I may looking for elegant/dynamic solution but no problem.
    The problem is with my logic I guess. So now its working fine with unlimited zooming action.

    Now I have an one more query, as QwtPlotMarker's are stick to the scale(say line is at X-Position 50) and if I zoom out, the scale is now showing 10 - 40. Now my Line Marker is disappear as its position is 50. So how I can prevent the Line Marker from going outside of the widget ? i.e., how I can set boundary for Line Marker ?

Similar Threads

  1. Replies: 2
    Last Post: 4th January 2019, 12:14
  2. Replies: 2
    Last Post: 20th July 2015, 07:14
  3. Replies: 2
    Last Post: 26th July 2013, 15:25
  4. QwtPlotMarker QwtPlotPicker
    By bss in forum Qwt
    Replies: 1
    Last Post: 15th June 2011, 13:55

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.