Results 1 to 16 of 16

Thread: QScrollArea vs. QAbstractScrollArea

  1. #1
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default QScrollArea vs. QAbstractScrollArea

    Hi all,

    I'm trying to write a thin Qt wrapper which allows to scroll a canvas rendered by a 3rd-party class Foo.

    This seems to work fine:
    Qt Code:
    1. class MyWrapper : public QScrollArea
    2. //class MyWrapper : public QAbstractScrollArea
    3. {
    4. Q_OBJECT
    5.  
    6. private:
    7. Foo _foo;
    8. QLabel _canvas;
    9.  
    10. public:
    11. MyWrapper()
    12. {
    13. setWidget(&_canvas); //QScrollArea
    14. // setViewport(&_canvas); //QAbstractScrollArea
    15. _canvas.setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    16. _foo.setHook(hook, this);
    17. }
    18.  
    19. //3rd-party class Foo signals "render finished" through this callback
    20. friend void hook(void *data, bool canceled);
    21.  
    22. public slots:
    23. void showRendered()
    24. {
    25. QImage img(reinterpret_cast<const uchar *>(_foo.buffer()),
    26. _pdfView->bufferWidth(),
    27. _pdfView->bufferHeight(),
    28. QImage::Format_ARGB32);
    29. _canvas.setPixmap(QPixmap::fromImage(img));
    30. _canvas.adjustSize();
    31. }
    32.  
    33. protected:
    34. void paintEvent(QPaintEvent *event)
    35. {
    36. _foo.update();
    37. }
    38.  
    39. void resizeEvent(QResizeEvent *event)
    40. {
    41. _foo.resize(viewport()->width(), viewport()->height());
    42. }
    43. };
    44.  
    45. void hook(void *data, bool canceled)
    46. {
    47. MyWrapper*wrapper = (PdfWidget *)data;
    48. //Foo::update() spawns a sparate thread
    49. QMetaObject::invokeMethod(wrapper, "showRendered", Qt::AutoConnection);
    50. }
    To copy to clipboard, switch view to plain text mode 

    As Foo provides everything needed to move/zoom/resize/pan the canvas, QAbstractScrollArea seems more appropriate to inherit from.
    However, if I apply the changes indicated in the above code snippet, nothing is painted at all in the viewport.

    What am I missing? Any help appreciated.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea vs. QAbstractScrollArea

    If you derive from the abstract class, you have to do the painting yourself in the paintEvent.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QScrollArea vs. QAbstractScrollArea

    Could you please elaborate on this?
    I thought setting the pixmap in showRendered() would do the painting, asynchronously though. Do I need to literally use a QPainter, and if so, why?

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea vs. QAbstractScrollArea

    There is no asynchronous painting on widgets in Qt. Everything has to be done in the paintEvent. Once a paint event is scheduled for a widget, Qt clears its contents and so you see nothing. You should store a pixmap with what Foo draws for you and render the appropriate part of it in the paintEvent() to the viewport.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QScrollArea vs. QAbstractScrollArea

    Thanks for your clear advice, I'll go for it.

    Quote Originally Posted by wysota View Post
    Once a paint event is scheduled for a widget, Qt clears its contents and so you see nothing.
    Didn't know the clearing, thx for pointing me there.

    If there's a problem with the asynchronous call, why does the code [seem to] work when subclassing QScrollArea?

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea vs. QAbstractScrollArea

    Because you are using setPixmap() which sets a pixmap on the label and schedules a paint event for the label. So in this case everything is correct, there is nothing "asynchronous" related to painting on widgets there. But you shouldn't do the thing you do by overriding paintEvent(). If at all, you should override resizeEvent() and call update() on _foo there.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QScrollArea vs. QAbstractScrollArea

    Thx again wysota, I very much appreciate your time and patience! However, I'm still not clear here.

    The only difference between MyWrapper inheriting from QScrollArea or QAbstractScrollArea - apart from the base class of course - is the way _canvas is made known to it. So it seems feasible that "ownership" means something different depending on whether I call QScrollArea::setWidget(&_canvas) or QAbstractScrollArea::setViewport(&_canvas). But I can't figure out in which way different.

    I understand that if I use a QPainter to paint a widget, I can only do so from within paintEvent(), as the QPainter class reference warns. What I don't understand is why I need to use a QPainter and cannot call _canvas.setPixmap(..) all the same when MyWrapper is a QAbstractScrollArea. This seems to not even depend on asynchronicity.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea vs. QAbstractScrollArea

    Quote Originally Posted by zaphod.b View Post
    The only difference between MyWrapper inheriting from QScrollArea or QAbstractScrollArea - apart from the base class of course - is the way _canvas is made known to it.
    The important part is that with QScrollArea _canvas is a full blown regular widget that acts on its own whereas when deriving from the abstract scroll area you as the author are responsible for drawing everything on the viewport.

    So it seems feasible that "ownership" means something different depending on whether I call QScrollArea::setWidget(&_canvas) or QAbstractScrollArea::setViewport(&_canvas). But I can't figure out in which way different.
    setWidget and setViewport do two completely different things. A viewport is strictly a canvas you can (and should) draw on. Its previous content is irrelevant, the view will take control over it, will erase it or draw on it when it sees fit. setWidget on the other hand inserts an external widget into the scroll area and the view is forbidden from drawing on it. It can only manipulate its geometry if you allow it to. The widget itself is responsible for rendering itself and managing its geometry.

    What I don't understand is why I need to use a QPainter and cannot call _canvas.setPixmap(..) all the same when MyWrapper is a QAbstractScrollArea. This seems to not even depend on asynchronicity.
    Because the view will draw over whatever the "viewport" renders itself and you will see nothing. At least that's theory. What happens in your particular case might be differnt - a human factor enters the picture here.

    One more thing - the widget can be larger than the viewport which is always the size of the abstract scroll area widget (of course without all the decorations, margins and scrollbars).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. The following user says thank you to wysota for this useful post:

    zaphod.b (7th July 2009)

  10. #9
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QScrollArea vs. QAbstractScrollArea

    I'm getting there at last. Excellent explanation, wysota, thanks a lot!

    What irritated me was that QAbstractScrollArea isn't abstract at all, so I wrongly assumed it would be more alike QScrollArea than it actually is. Also, viewport()/setViewport() get/set a QWidget, yet the required properties merely seem to be to provide an area and eventually be painted on. (After all, with QPainter viewport()/setViewport() work on QRect, which seems logical as QPainter already knows about the paint device and nothing else is needed. And the QAbstractScrollArea constructor/destructor documentation hints that the class is considered to be just a viewport with some decoration API.) Is there a deeper reason why the Trolls still went with a QWidget but ignore most of its functionality?

    Actually, when subclassing QAbstractScrollArea, I don't need to setVieport() at all and _canvas is dispensible. I wonder in which scenario one would need to setViewport()?

    Anyway, I can get on from here and sleep well.
    Thx again!

  11. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea vs. QAbstractScrollArea

    Quote Originally Posted by zaphod.b View Post
    What irritated me was that QAbstractScrollArea isn't abstract at all
    It is. It can be perceived as "something you can scroll".

    Is there a deeper reason why the Trolls still went with a QWidget but ignore most of its functionality?
    I don't understand what you mean.

    I wonder in which scenario one would need to setViewport()?
    For example if you would like to set a QGLWidget as the viewport, as we often do for QGraphicsView.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #11
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QScrollArea vs. QAbstractScrollArea

    Quote Originally Posted by wysota View Post
    Quote Originally Posted by zaphod.b View Post
    What irritated me was that QAbstractScrollArea isn't abstract at all
    It is. It can be perceived as "something you can scroll".
    Well, yes - but not abstract as in pure virtual. Please don't ask for logic; it's only how I initially perceived QAbstractScrollArea after switching from QScrollArea.

    Is there a deeper reason why the Trolls still went with a QWidget but ignore most of its functionality?
    I don't understand what you mean.
    A QPaintDevice has a width and height too. So if being paintable and having a size is all that's needed for a viewport, my first guess would be to pass a QPaintDevice instead of a full-fledged QWidget. But this may well be a misconception owed to my little knowledge, as your QGLWidget example indicates.

  13. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea vs. QAbstractScrollArea

    QPaintDevice is pure virtual
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. #13
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QScrollArea vs. QAbstractScrollArea

    Quote Originally Posted by wysota View Post
    QPaintDevice is pure virtual
    That's ok. Just declare QAbstractScrollArea::setViewport(QPaintDevice *); and leave it to the caller if he passes a QWidget or another QPaintDevice instance. If there isn't a good reason for a QWidget formal parameter, that is...

  15. #14
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea vs. QAbstractScrollArea

    Well... the viewport is a widget. The abstract scroll area is composed of the "main" widget, two scrollbars and a viewport. At some point you need to draw on the viewport and if you were drawing on anything else than a widget (like a printer) it might be hard to copy the result to screen later on.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  16. #15
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QScrollArea vs. QAbstractScrollArea

    Quote Originally Posted by wysota View Post
    if you were drawing on anything else than a widget (like a printer) it might be hard to copy the result to screen later on.
    Good point.

    I think I'd rather not pester you further on this unless I achieve better permeation of the topic...
    For I might want to resort to your help again in the future.

    Thank you!

  17. #16
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QScrollArea vs. QAbstractScrollArea

    Don't worry, there is no risk for you
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. several questions about QScrollArea
    By Sheng in forum Qt Programming
    Replies: 1
    Last Post: 4th June 2009, 16:59
  2. Replies: 1
    Last Post: 13th September 2008, 12:00
  3. Dynamic updates of a QWidget in a QScrollArea
    By plamkata in forum Qt Programming
    Replies: 2
    Last Post: 21st July 2008, 00:45
  4. QScrollArea and resizing
    By rarefluid in forum Qt Programming
    Replies: 8
    Last Post: 22nd July 2007, 15:18
  5. Replies: 2
    Last Post: 8th October 2006, 21:14

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.