Results 1 to 3 of 3

Thread: Drawing over content widgets? (overlay)

  1. #1
    Join Date
    Jan 2006
    Qt products
    Qt3 Qt4

    Unhappy Drawing over content widgets? (overlay)

    I do have a widget that is composed of some other widgets, and I want to draw something over it, how can I do that?

    At first I thought that Just drawing on the paintEvent(...) should be enought, but it gets drawn under the contained widgets. Then I though about forcing to draw the children first, then my paint event... but no luck again. Basic example code looks like this:

    Qt Code:
    1. class PaintWidget : public QWidget{
    2. Q_OBJECT
    3. public:
    4. PaintWidget(QWidget *parent){
    5. b=new MyPushButton("Hello world",this);
    6. }
    8. protected:
    9. virtual void paintEvent(QPaintEvent *event){
    10. b->repaint();
    11. QPainter p(this);
    12. p.setPen(QColor("red"));
    13. p.drawLine(0,0,width(),height());
    14. event->ignore();
    15. }
    16. MyPushButton *b;
    17. };
    To copy to clipboard, switch view to plain text mode 

    Then I thought also to force by hand redrawing calling the paintEvent on the children first, and hiding the widget... But a "QPainter::begin: Widget painting can only begin as a result of a paintEvent" message tells me I can not do it in this way.

    Anybody any idea?

    (looking at the designer source code I dont get any clear idea on how to do it)

    At I put the full example.


  2. #2
    Join Date
    Jan 2006
    Qt products
    Qt3 Qt4

    Default Re: Drawing over content widgets? (overlay)

    My own repy, just for the forum annals, of why this seems to be impossible to achieve fully, but possible partially. And finally a small chance to make it possible.

    I achieved at most to be able to draw under the widget. That is accomplished just by setting the Qt::WA_ContentsPropagated on the parent children. This way it does not redraw it's background, and uses the one the parent left.

    I managed to make sure that the order everything is drawn is right, to draw something inside the widget I want to draw over, and then draw something over. My results are: Qt (at least over X11), in the way it manages QPainters clips that region out. The only widget allowed to draw there is to use that QWidget's QPainter object.

    So with that thing in mind, it is possible, with some Flag black magic, draw over the widget:

    1. Reimplement the widget you want to draw over, and do a wrapper method to avoid the protect clause of the paintEvent() method.
    2. Set the children Qt::WA_PaintOutsidePaintEvent to true, so he paintEvent can be called by your own code not coming from the appropiate event.
    3. On you parent widget or at the new widget, disable updates (setUpdatesEnabled(false))
    4. On your parent widget draw your thing, then call the wrapper for paintEvent(...) at your childs, and finally use your child QPainter and draw whatever you want to draw with your childs QPainter. I repeat, you have to use your own QPainter, and the your child one. At least two QPainters.

    As you can see the solution is ugly. It achieves the goal to draw over a child widget, but the drawbacks are: you have to make a new class with a few "tricks" to allow painting outside the class, and you have to be carefull to draw everything at least in the proper QPainters.

    For this two things... I'm still waiting for the Qt4 QCanvas. I can afford the reimplement thing as I want to draw over my own implemented widgets, but I can not afford to draw everything at least two times.

    To me it seems there should still be some way, as the first aproach (draw under the widgets) works without the childs QCanvas, but if you enable painting, the children is drawn after the parent (to correctly use the background, I guess), and if you disable updates on child (second aproach, custom child's public paintEvent), the parent gets that region clipped.

    Somebody know how to avoid this?

    Mandatory source code:
    Qt Code:
    1. class MyPushButton:public QPushButton{
    2. public:
    3. MyPushButton(const char *txt,QWidget *parent):
    4. QPushButton(txt,parent){
    5. setAttribute(Qt::WA_PaintOutsidePaintEvent,true );
    6. setUpdatesEnabled(false);
    7. };
    8. void _paintEvent(QPaintEvent *e){ this->paintEvent(e); };
    9. protected:
    10. };
    12. class PaintWidget:public QWidget{
    13. Q_OBJECT
    14. public:
    15. PaintWidget(QWidget *parent){
    16. b=new MyPushButton("Hello world",this);
    17. }
    18. protected:
    19. virtual void paintEvent(QPaintEvent *event){
    20. b->_paintEvent(event);
    21. QPainter p(this);
    22. p.setPen(QColor("red"));
    23. p.drawLine(0,0,width(),height());
    24. QPainter q(b);
    25. q.setPen(QColor("red"));
    26. q.drawLine(0,0,width(),height());
    27. }
    28. MyPushButton *b;
    29. };
    To copy to clipboard, switch view to plain text mode 

    Thanks for reading.

  3. #3
    Join Date
    Jan 2006
    Thanked 18 Times in 17 Posts
    Qt products
    Unix/X11 Windows

    Default Re: Drawing over content widgets? (overlay)

    similar question:

    lets assume my window contains some internal layout.

    now, at some point, I want to display a widget (in my case a progress bar) floating at the bottom left, which will be hidden at a specific time. Just imagine the progress bar yousee on firefox when posting, 30 pixels up, just floating.

    how can I implement such thing?

Similar Threads

  1. Drawing standard widgets using a custom paint engine
    By Waywocket in forum Qt Programming
    Replies: 26
    Last Post: 21st October 2010, 21:40
  2. Problems with QString
    By cyberboy in forum Qt Programming
    Replies: 2
    Last Post: 13th October 2008, 09:18
  3. Replies: 2
    Last Post: 18th March 2008, 00:49


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.