Results 1 to 13 of 13

Thread: Painting on a QLabel

  1. #1
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Painting on a QLabel

    I want to draw points on a label imbedded in a widget.

    So, in the paintEvent for the widget I create a QPainter and pass it a pointer to a QPixmap I got from the label using QPixmap::fromImage().

    I draw points using the painters drawPoint(int x, int y) method. When done with all the drawing, I use the label's setPixmap method, passing QPixmap referenced by the pointer passed to the QPainter constructor.

    All of this works, except the setPixmap seems to partially break the Qt's event processing. I can still move windows and do many GUI things, but, for example, radio buttons don't uncheck after changing what's checked unless I move the window.

    If I remove the setPixmap from the paintEvent handler, all the event processing works normally, but the points don't show up on the label.

    Here are some code fragments (I'm a Qt newbie, and here it probably shows!)

    Qt Code:
    1. void PlaceStartLine::paintEvent(QPaintEvent *event)
    2. {
    3. QPainter painter(&qp);
    4.  
    5. QPen myPen(Qt::red, 5, Qt::SolidLine,Qt::RoundCap);
    6. painter.setPen(myPen);
    7. good_rows.clear();
    8.  
    9. for (int i=0; i<tableWidget->rowCount();i++)
    10. {
    11. bool ok_x;
    12. bool ok_y;
    13. bool ok_phys_x;
    14. bool ok_phys_y;
    15. double phys_x;
    16. double phys_y;
    17. int x;
    18. int y;
    19.  
    20.  
    21.  
    22. x= tableWidget->item(i,2)->text().toInt(&ok_x);
    23. if (ok_x)
    24. tableWidget->item(i,2)->setBackgroundColor(Qt::green);
    25. else
    26. tableWidget->item(i,2)->setBackgroundColor(Qt::red);
    27.  
    28. y= tableWidget->item(i,3)->text().toInt(&ok_y);
    29.  
    30. if (ok_x)
    31. tableWidget->item(i,3)->setBackgroundColor(Qt::green);
    32. else
    33. tableWidget->item(i,3)->setBackgroundColor(Qt::red);
    34.  
    35. phys_x = tableWidget->item(i,0)->text().toDouble(&ok_phys_x);
    36. if (ok_phys_x)
    37. tableWidget->item(i,0)->setBackgroundColor(Qt::green);
    38. else
    39. tableWidget->item(i,0)->setBackgroundColor(Qt::red);
    40.  
    41. phys_y = tableWidget->item(i,1)->text().toDouble(&ok_phys_y);
    42. if (ok_phys_y)
    43. tableWidget->item(i,1)->setBackgroundColor(Qt::green);
    44. else
    45. tableWidget->item(i,1)->setBackgroundColor(Qt::red);
    46.  
    47. if (! (ok_x && ok_y)) continue;
    48.  
    49. good_rows.push_back(i);
    50. painter.drawPoint(x,y);
    51.  
    52. }
    53. startLineImage->setPixmap(qp);
    54. qp.scaled(grabbedImage->size(),Qt::KeepAspectRatio);
    55.  
    56. //startLineImage->setPixmap(qp);
    57.  
    58.  
    59. //event->accept();
    60. }
    To copy to clipboard, switch view to plain text mode 

    If I uncomment the line:
    Qt Code:
    1. startLineImage->setPixmap(qp);
    To copy to clipboard, switch view to plain text mode 

    Then the points get drawn, but event processing seems crippled. If I omit the line, everything works fine, but I don't see the drawn points, presumably because they are drawn on a copy of the labels pixmap, so I need to do a stPixmap(qp) after drawing.

    I played with adding the event->accept(), but it made no difference that I could tell.

    Anybody have a clue on what's going on and/or how to fix?

    Thanks,

    Dave Thomas


    Added after 4 minutes:


    Ok, I fixed it, but I don't totally understand.

    I added code to just do the painting one time, when I know something changed and everything works nicely now.

    I guess there was just too much to do for EACH paint event?

    Dave Thomsa
    Last edited by davethomaspilot; 13th July 2012 at 20:42.

  2. #2
    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: Painting on a QLabel

    Are you sure that your code wasn't resulting in a recursive (or maybe just multiple) paint event? If you do something inside the paint event which results in the widget thinking it has been resized or needs to be repainted, this could cause that.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Painting on a QLabel

    Hmm, not that I know of it, but good point.

    The code for the QPaint is above. Would anything there cause the QPaint to be executed again before it completed? It set colors of cells, would that cause another QPaint event for the running one completed?

    Thanks,

    Dave Thomas

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: Painting on a QLabel

    Quote Originally Posted by davethomaspilot View Post
    Would anything there cause the QPaint to be executed again before it completed? It set colors of cells, would that cause another QPaint event for the running one completed?
    Yes Half of your code above is forbidden to put in a paint event. paintEvent() of widget X is supposed to draw the contents of widget X, not do many other things that have nothing to do with drawing widget X.
    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 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Painting on a QLabel

    Ok, makes sense.

    Thanks!

    Dave THomas

  6. #6
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Painting on a QLabel

    I removed everthing from the QPaintEvent except the code that:

    gets an x & y from a tableWidget;
    draws a point on (a copy?) of a labels QPixmap using that x, y.
    assigns the QPixmap with the drawn points to a label

    I still get the same crippled event handling, unless I add a flag for the method to be executed only once.

    Here's the paintEvent handler:


    Qt Code:
    1. void PlaceStartLine::paintEvent(QPaintEvent *event)
    2. {
    3.  
    4. //if(repainted) return;
    5.  
    6. QPainter painter(&qp);
    7.  
    8. QPen myPen(Qt::red, 5, Qt::SolidLine,Qt::RoundCap);
    9. painter.setPen(myPen);
    10.  
    11.  
    12. for (int i=0; i<tableWidget->rowCount();i++)
    13. {
    14. bool ok_x;
    15. bool ok_y;
    16.  
    17. int x;
    18. int y;
    19.  
    20. x= tableWidget->item(i,2)->text().toFloat(&ok_x);
    21. y= tableWidget->item(i,3)->text().toFloat(&ok_y);
    22.  
    23. if (ok_x && ok_y)
    24. painter.drawPoint(x,y);
    25.  
    26. }
    27. qp.scaled(grabbedImage->size(),Qt::KeepAspectRatio);
    28. startLineImage->setPixmap(qp);
    29.  
    30. repainted=true;
    31.  
    32. }
    To copy to clipboard, switch view to plain text mode 

    If recursion is the issue, then it's the setPixmap method that causes it. How does one draw on a label, if you can't associate the PixMap drawn on to a label?

    Half of your code above is forbidden to put in a paint event.
    Where can I find a definition of what is forbidden to put in a paint event?

    Thanks!

    Dave Thomas

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: Painting on a QLabel

    It's still wrong. You can't call setPixmap from within a paint event. I think you misunderstand what paintEvent is supposed to do. If you have a paintEvent of a widget class "X" then the code you put in there should paint the canvas of the instance of widget "X". It should not manipulate properties of any objects and is not meant to do anything with children of that class, including that it is supposed to set what the contents of child widgets should look like. To me it seems the code you have should simply be put in a different function, most probably in a slot connected to a signal that is emitted whenever data in tableWidget changes.

    As for what's forbidden -- a good rule of a thumb is that you should not call any non-const functions other than ones manipulating local variables declared in the paintEvent body. In your case you can manipulate the "painter" object but not the "startLineImage" object.
    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.


  8. #8
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Painting on a QLabel

    If I don't call setPixmap, the label's pixmap doesn't get updated with the new drawn points. That's just drawing on a copy of the labels pixmap.

    So, my question is still

    "How does one draw on a label, if you can't associate the PixMap you draw on to the label"?

    In other words, if I don't do the setPixmap call in the paint event handler, nothing that is drawn is ever seen.

    Thanks,

    Dave Thomas

    Maybe a key assumption I'm making isn't valid.

    I thought the only place you could use the draw methods of a Painter was in the paint event handler?

    It that's not ture, then sure, I can do the draw and the assignment of the newly update pixmap to the label outside the handler.

    Thanks,

    Dave Thomas

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: Painting on a QLabel

    Quote Originally Posted by davethomaspilot View Post
    "How does one draw on a label, if you can't associate the PixMap you draw on to the label"?
    You can but not in paintEvent. Do it wherever else you want.

    I thought the only place you could use the draw methods of a Painter was in the paint event handler?
    Only if you draw on a widget. Here you're drawing on a pixmap.

    I don't know what your particular usecase is but I'd like to present an alternative, simpler, approach. Don't use a label at all -- draw directly on the widget (of course this time from within the paint event).
    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.


  10. #10
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Painting on a QLabel

    "You can but not in paintEvent. Do it wherever else you want."

    But if you can only draw in the paintEvent, the setPixMap has to be AFTER the points are drawn. How does one make sure that happens after the draws occur, if you don't set the pixmap in the event handler?


    The points need to be drawn on the Pixmap. They correspond to physical x,y locations mapped to specific points on the Pixmap, with a coordinate system referenced to the Pixmap, not the widget.

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: Painting on a QLabel

    Quote Originally Posted by davethomaspilot View Post
    "You can but not in paintEvent. Do it wherever else you want."

    But if you can only draw in the paintEvent, the setPixMap has to be AFTER the points are drawn. How does one make sure that happens after the draws occur, if you don't set the pixmap in the event handler?


    The points need to be drawn on the Pixmap. They correspond to physical x,y locations mapped to specific points on the Pixmap, with a coordinate system referenced to the Pixmap, not the widget.
    You have fixed yourself on drawing the points in the event handler. Here is a sample app, study it:

    Qt Code:
    1. class Widget : public QLabel {
    2. public:
    3. Widget() : QLabel() {
    4. m_px = QPixmap(400, 400);
    5. m_px.fill(Qt::transparent);
    6. setPixmap(m_px);
    7. }
    8. void addPoint(const QPoint &pt) {
    9. QPainter p(&m_px);
    10. p.drawPoint(pt);
    11. p.end();
    12. setPixmap(&m_px);
    13. }
    14. protected:
    15. void mousePressEvent(QMouseEvent *e) {
    16. addPoint(e->pos());
    17. }
    18. QPixmap m_px;
    19. };
    To copy to clipboard, switch view to plain text mode 

    or similar without using QLabel at all:

    Qt Code:
    1. class Widget : public QWidget {
    2. public:
    3. Widget() : QWidget() {}
    4.  
    5. void addPoint(const QPoint &pt) {
    6. m_pts << pt;
    7. update();
    8. }
    9. protected:
    10. void mousePressEvent(QMouseEvent *e) {
    11. addPoint(e->pos());
    12. }
    13. void paintEvent(QPaintEvent *e) {
    14. QPainter p(this);
    15. p.drawPoints(m_pts);
    16. }
    17. QPolygon m_pts;
    18. };
    To copy to clipboard, switch view to plain text mode 

    plus, of course, main():
    Qt Code:
    1. int main(int argc, char **argv) {
    2. QApplication app(argc, argv);
    3. Widget w;
    4. w.show();
    5. return app.exec();
    6. }
    To copy to clipboard, switch view to plain text mode 
    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. #12
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Painting on a QLabel

    Thanks for takingl the time to send the example code snippets. That's certainly above and beyond the call of duty!

    The key point I didn't understand was that you could create a QPainter outside a paintEvent handler and do the drawing there. So, I really don't even need a paintEvent handler.

    For what appears to be no good reason, the examples I found instantiated a QPainter inside the paintEvent handler, so I just did it that way.

    So now, I see no need in my application to have a paintEvent handler. Just create a QPainter, draw the points on a Pixmap, and assign the Pixmap to the label. Like you did in your first code snippet.

    I'm missing your point about not using a label and why that's simpler. In my case, I have a widget with a table, buttons, and a label that's just an image. The coordinate system for the draw points is relative to the label's position, not the containing widget's position.

    I guess you're just saying that you can do the drawpoints in a paintEvent handler, if you're painting on somthing like a QPolygon. Then you don't have to worry about copying what you just painted on using something like a setPixmap. But it's still easier to not use the paintEvent at all!

    Why does your second example need the paintEvent. Couldn't those two lines of code be in your add_points method?

    Thanks,

    Dave Thomas




    Thanks,

    Dave

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: Painting on a QLabel

    Quote Originally Posted by davethomaspilot View Post
    For what appears to be no good reason, the examples I found instantiated a QPainter inside the paintEvent handler, so I just did it that way.
    ... and they passed "this" as the argument for the constructor. That's the key point here.

    I'm missing your point about not using a label and why that's simpler. In my case, I have a widget with a table, buttons, and a label that's just an image. The coordinate system for the draw points is relative to the label's position, not the containing widget's position.
    There are many reasons and there is no need to discuss them here. If using an intermediate pixmap works for you then that's fine.

    I guess you're just saying that you can do the drawpoints in a paintEvent handler,
    I suggest you take a look at source code of some custom widgets, it might open a whole new world for you.

    if you're painting on somthing like a QPolygon.
    I'm not painting on a QPolygon (it's just a vector of points). I'm painting on a widget.

    But it's still easier to not use the paintEvent at all!
    You are using paintEvent. You just didn't implement it yoruself. If your points change very often then your current implementation will be twice as slow (or worse on X11) than my second implementation because you're painting everything twice -- once points on a pixmap and then pixmap on the widget.

    Why does your second example need the paintEvent. Couldn't those two lines of code be in your add_points method?
    No. paintEvent() is called whenever the widget needs redrawing and that can happen because of reasons other than points being added (e.g. when you resize the window, minimize it or sometimes even move some other window over it. In other words paintEvent() is not meant to update the state of the widget when something changes, it is meant to visualize the current state of the widget (whatever it might be) -- it has no memory and no sense of "change". It just lives now and today.
    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. Painting an overlay on a QLabel->QImage
    By papillon in forum Qt Programming
    Replies: 7
    Last Post: 10th July 2012, 09:28
  2. Replies: 8
    Last Post: 5th July 2011, 07:32
  3. Replies: 1
    Last Post: 29th September 2009, 19:44
  4. Replies: 1
    Last Post: 2nd August 2008, 15:46
  5. QLabel Painting
    By vijay anandh in forum Qt Programming
    Replies: 4
    Last Post: 15th May 2006, 13:12

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.