Results 1 to 17 of 17

Thread: QwtPlot inside a QGraphicsView

  1. #1
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default QwtPlot inside a QGraphicsView

    I have placed several QwtPlots on a QGraphicsView used to resemble a textual document.
    I want to use the zooming capabilities of the QGraphicsScene, of course.
    This is what I get at default zooming factors, that is, a neat and perfect plot:

    nozoom.png

    But, when I operate some zooming on the scene, this is what I get:

    yeszoom.png

    As you can see, the labels and the axes of the plot are still perfect and vectorial, whereas the canvas looks grainy, such as if it were a bitmap that has been scaled up.
    What I do not understand is why the characters in the labels of the axes look good, but the canvas looks so horrible.
    Any help or clue is appreciated, thanks.

  2. #2
    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: QwtPlot inside a QGraphicsView

    What happens when you disable the internal cache of the canvas ( see QwtPlotCanvas::setPaintAttribute() ) ?

    Uwe

  3. #3
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default Re: QwtPlot inside a QGraphicsView

    Hi Uwe,

    Qt Code:
    1. setPaintAttribute(QwtPlotCanvas::BackingStore, false)
    To copy to clipboard, switch view to plain text mode 

    did the trick, see below

    yeszoomfine.png

    Thank you!

    The print preview is still grainy (the axes, too), but after printing out it is quite unnoticeable

  4. #4
    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: QwtPlot inside a QGraphicsView

    I wouldn't disable the backingstore completely - instead invalidate it manually ( QwtPlotCanvas::invalidateBackingstore() ) when you zoom in/out.

    But I strongly recommend not using QGraphicsView: you will run into problems like yours and serious performance issues when zooming in deep. You can zoom in/out using QwtPlot in a better way and QwtPlotRenderer is much more powerful for creating vector graphics.

    As long as there is no real strong reason for embedding a QwtPlot widget into a QGraphicsView: don't do it !

    Uwe
    Last edited by Uwe; 20th January 2013 at 09:43.

  5. #5
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default Re: QwtPlot inside a QGraphicsView

    Ok, I will disable and re-enable it during zooming operations.
    Unfortunately, I need to place the plots inside a WYSIWYG document page that contains also text, images, and other things, for which I need to adopt a QGraphicsView.
    I have a last question: how is it possible to reimplement the method QwtPlotCanvas::drawBorder? Do I need to reimplement also the whole QwtPlot and assemble manually the canvas (reimplemented), axes, and all other things?

  6. #6
    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: QwtPlot inside a QGraphicsView

    I have a last question: how is it possible to reimplement the method QwtPlotCanvas::drawBorder?
    Better tell me what you want to do first.

    Uwe

    PS: if you want to use the zooming feature of QGraphicsView to see more details of the plot be warned, that this won't work, when the real device resolution is hidden behind logical geometries !

  7. #7
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default Re: QwtPlot inside a QGraphicsView

    I want to draw a one-pixel wide cosmetic black border all around the canvas, as in the previous pics I posted. I am currently doing it in the reimplementation of
    QwtPlot::drawCanvas;, after finding that other existing methods did not work properly. I mean, it works perfectly now, I was just wondering whether reimplementing the QwtPlotCanvas::drawBorder method would have been cleaner and/or more elegant.

    As for the zoom, there are two types I am using.

    1 - fixed the zoom of the whole document page, the user can zoom in and out in the data series inside of the plot
    2 - fixed the zoom in the plot, the user can zoom in and out in the document page

    As far as I can tell and see, both methods are performing well and give very good results, also after your precious suggestion.

  8. #8
    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: QwtPlot inside a QGraphicsView

    Quote Originally Posted by gibi70 View Post
    I want to draw a one-pixel wide cosmetic black border all around the canvas, ...
    Qt Code:
    1. canvas()->setLineWidth( 1 );
    2. canvas()->setFrameStyle( QFrame::Plain | QFrame::Box );
    To copy to clipboard, switch view to plain text mode 

    HTH,
    Uwe

  9. #9
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default Re: QwtPlot inside a QGraphicsView

    Hi Uwe, this is how I'd like the canvas (reimplementing drawCanvas)

    drawcanvas.jpg

    and this is how it appear setting the line width and style of the frame

    linewidth1.jpg

    As you can see, there is a small extra space between the grid lines and the border.

    Regarding the invalidation of the backingstore, as you wrote before, do I need to invalidate it before the zooming operation or just after having zoomed? Do I need to replot() in order to redraw the plot after that?

  10. #10
    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: QwtPlot inside a QGraphicsView

    As you can see, there is a small extra space between the grid lines and the border.
    See QwtPlotLayout::setCanvasMargin() or QwtPlotLayout::setAlignCanvasToScales().
    Regarding the invalidation of the backingstore, as you wrote before, do I need to invalidate it before the zooming operation or just after having zoomed?
    Thinking about it twice I guess ( have not checked it myself ) that QGraphicsView framework sets up a QPainter transformation for zooming, what will always end in something ugly, when there is a backing store. So disabling the backing store completely is probably the right solution.

    The backing store of the canvas is important in combination with widget overlays ( f.e. rubber bands ), what will result in complete replots otherwise - often too slow for such operations. If you don't need them I wouldn't expect a problem with disabling it.

    By the way: when I'm right with my guess above you should check if you want the following flag:

    Qt Code:
    1. QwtPainter::setRoundingAlignment( false );
    To copy to clipboard, switch view to plain text mode 
    Without aligning you might have effects because Qt aligns objects not properly ( f.e. the bottom/right borders of rects depending on left/top ), but with aligning I'm afraid Qwt aligns to logical coordinates and you will see rounding errors getting worse with increasing the zoom level.

    One more comment: Qt renders before it clips, what might end in horrible performance issues, when you have lines very far outside the visible area. That's why Qwt does a polygon clipping ( QwtPlotCurve::ClipPolygons ) against the canvas geometries before passing the result to QPainter. In your layout you will have a huge canvas ( clipped by the viewport of the grahpics view ), what disables the effect of the polygon clipping. So be aware of this problem, when you want to zoom in very deep.

    Uwe

  11. #11
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default Re: QwtPlot inside a QGraphicsView

    Hi Uwe, thanks for the hints.

    Only a completely disabled backingstore works for the case above, any other combination of parameters did not produce good results. BTW, in this way canvas transparency is perfect, whereas in the other case there are strange graphical effects on it.

    Unfortunately, I need to plot multiple permanent pickers on the canvas (uhm, I'd like to ask something on this too...), so I do see a slow down in that case. I am thinking about completely deleting and recreating the plot during the zooming operation, might it work?

  12. #12
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default Re: QwtPlot inside a QGraphicsView

    Hello Uwe, I hope you are still following this thread.
    Everything works almost perfectly, after doing adjustments here and there.
    However, I noticed a "problem" when exporting to PDF, which might not be entirely Qwt-related, I think.
    If I export the single QwtPlot to PDF, it produces fine vectorial graphics on the PDF file itself. But, if I export to PDF the QGraphicsScene which contains the QwtPlot, it replaces the plot area (with labels, axes, and so on) with a bitmap.
    Is that related to the fact that I put the QwtPlot itself inside a QGraphicsProxyWidget?

  13. #13
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QwtPlot inside a QGraphicsView

    Is that related to the fact that I put the QwtPlot itself inside a QGraphicsProxyWidget?
    I think that's correct - QGraphicsProxyWidget paints its content to a pixmap (which serves as a QPaintDevice). QwtPlot actually renders its content to a PDF printer in vector format to create the PDF output file.

    You might be able to work around this by deriving a custom widget from QGraphiscProxyWidget and reimplementing whatever method is called to produce the PDF output. I am not sure how you merge the two bits of PDF though. The QwtPlot output is meant to be standalone, I think.

  14. #14
    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: QwtPlot inside a QGraphicsView

    Quote Originally Posted by d_stranz View Post
    The QwtPlot output is meant to be standalone, I think.
    No - it isn't:

    Qt Code:
    1. void QwtPlotRenderer::render( QwtPlot *, QPainter *, const QRectF & ) const;
    To copy to clipboard, switch view to plain text mode 
    Uwe

  15. #15
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default Re: QwtPlot inside a QGraphicsView

    Ok, I have reimplemented QGraphicsProxyWidget in this way
    Qt Code:
    1. class MyProxyWidget : public QGraphicsProxyWidget
    2. {
    3. public:
    4.  
    5. MyProxyWidget(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0)
    6. : QGraphicsProxyWidget(parent, wFlags)
    7. {
    8. }
    9.  
    10. virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    11. {
    12. //QGraphicsProxyWidget::paint(painter, option, widget);
    13. QwtPlotRenderer rdr;
    14. rdr.render((QwtPlot *) this->widget(), painter, boundingRect());
    15. }
    16. private:
    17. };
    To copy to clipboard, switch view to plain text mode 
    During common visualization on the GUI, the look is very good and with minor adjustments it could be even better. Now, when I export to pdf all the axes ticks, fonts, labels, etc, the grid lines, the plot title are vectorial, but they are huge! They almost fill all the space assigned to the plot item and practically no curve can be seen. Maybe it depends on the boundingRect() size I am passing to the render method?

  16. #16
    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: QwtPlot inside a QGraphicsView

    No this should be because of the painter transformation - might be a problem of Qwt don't know.

    I would try to do something like this:

    Qt Code:
    1. virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    2. {
    3. if ( painter->paintEngine()->type() == QPaintEngine::Pdf )
    4. {
    5. painter->save();
    6.  
    7. const QRectF br = painter-> transform().mapRect( boundingRect() );
    8. painter->resetTransform();
    9.  
    10. QwtPlotRenderer rdr;
    11. rdr.render( (QwtPlot *) this->widget(), painter, br );
    12.  
    13. painter->restore();
    14. return;
    15. }
    16.  
    17. QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    18. }
    To copy to clipboard, switch view to plain text mode 
    Uwe

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

    gibi70 (26th February 2013)

  18. #17
    Join Date
    Jan 2013
    Posts
    12
    Thanks
    2

    Default Re: QwtPlot inside a QGraphicsView

    Yep, this works beautifully!

Similar Threads

  1. Qslider inside qgraphicsview
    By MAX1971 in forum Newbie
    Replies: 0
    Last Post: 23rd October 2012, 07:34
  2. Replies: 13
    Last Post: 18th December 2009, 10:43
  3. QGraphicsView and QwtPlot
    By Indalo in forum Qwt
    Replies: 1
    Last Post: 16th November 2009, 08:17
  4. Replies: 0
    Last Post: 4th November 2009, 07:12
  5. QwtPlot inside QScrollArea
    By mastupristi in forum Qwt
    Replies: 3
    Last Post: 13th October 2009, 05:28

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.