Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QPaintEvent in MainWindow

QPaintEvent in MainWindow

Scheduled Pinned Locked Moved Unsolved General and Desktop
qprinteventqprinterqmainwindow
20 Posts 4 Posters 11.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Donn
    wrote on 10 Mar 2016, 13:41 last edited by Donn 3 Oct 2016, 13:42
    #1

    I have the QMainWindow widget and two QLabel widgets inside it to display images and one QCheckBox widgte. In those two labels I display two images and after I check the Checkbox option I want that in one of those images some figures would be drawn on top of the displayed image. After I uncheck the checbox I want that the image returns as it was before painting all the stuff. I know that QPaintEvent can be used here but I don't want it to be trigged so often as some other activities are done in QMainWindow which would cause to trigger this event too often. So far I have this:

    void MainWindow::paintEvent(QPaintEvent *e)
    {
        if (ui->checkBox->isChecked())
        {
            QPainter painter(&image);
            painter.drawLine(10, 10, 150, 150);
            ui->label->setPixmap(QPixmap::fromImage(image));
        }
        else
        {
            // back to original image
        }
    }
    

    Is there a way to control paintEvent that it would be triggered only when I check the checkbox? Because now it will be triggered many times and else part will be done all the time when checkbox is not checked.

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 10 Mar 2016, 14:01 last edited by
      #2

      Hi,

      Why not connect a slot to the toggled signal for the QCheckBox and change the image there ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Donn
        wrote on 10 Mar 2016, 14:32 last edited by
        #3

        I only need that some figures are drawn on top of the existing image with QPainter whenever the checkbox is checked and when I uncheck it returns to the original image. I read that QPainter can be used only inside painterEvent, therefore, I don't see how toggled signal would help me unless you could clarify it :)

        K 1 Reply Last reply 10 Mar 2016, 15:03
        0
        • D Donn
          10 Mar 2016, 14:32

          I only need that some figures are drawn on top of the existing image with QPainter whenever the checkbox is checked and when I uncheck it returns to the original image. I read that QPainter can be used only inside painterEvent, therefore, I don't see how toggled signal would help me unless you could clarify it :)

          K Offline
          K Offline
          kshegunov
          Moderators
          wrote on 10 Mar 2016, 15:03 last edited by kshegunov 3 Oct 2016, 15:13
          #4

          @Donn
          If the figures are drawn over the label, why are you drawing them in the main window's paint event? And, no you can't or rather shouldn't depend on when the paint events are scheduled. You can get multiple spontaneous (such that come from the underlying OS) paint events when a widget is shown/overlapped/revealed. The simplest way would be to derive from the QLabel or even QWidget and draw your pixmap manually, then when there's a paint event just do the painting. The toggling of the checkbox would simply set an internal flag for your custom widget. Something like this (untested, but with a bit of tweaking should work fine):

          class MyLabelWithOverlay : public QLabel
          {
          public:
               MyLabelWithOverlay (QWidget * parent = NULL)
                     : QLabel(parent), overlayEnabled(false)
               {
               }
          
          public slots:
               void enableOverlay(bool enabled)
               {
                    overlayEnabled = enabled;
               } 
          
          protected:
               virtual void paintEvent(QPaintEvent * event)
               {
                    QPixmap pix = pixmap();
                    qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
          
                    QTransform transform;
                    transform.scale(ratio, ratio);
          
                    QRect sourceRect = transform.mapRect(event->rect());
          
                    QPainter painter(this);
                    painter.drawPixmap(event->rect(), pix, sourceRect);
          
                    if (overlayEnabled)  {
                        // Draw your lines here
                    }
               }
          
          private:
               bool overlayEnabled;
          }
          

          You connect the QCheckBox's toggled(bool) signal to the enableOverlay(bool) slot and that's mostly it.

          EDIT: I've added the proper casting where the ratio is calculated.

          Kind regards.

          Read and abide by the Qt Code of Conduct

          D 1 Reply Last reply 10 Mar 2016, 16:38
          0
          • K kshegunov
            10 Mar 2016, 15:03

            @Donn
            If the figures are drawn over the label, why are you drawing them in the main window's paint event? And, no you can't or rather shouldn't depend on when the paint events are scheduled. You can get multiple spontaneous (such that come from the underlying OS) paint events when a widget is shown/overlapped/revealed. The simplest way would be to derive from the QLabel or even QWidget and draw your pixmap manually, then when there's a paint event just do the painting. The toggling of the checkbox would simply set an internal flag for your custom widget. Something like this (untested, but with a bit of tweaking should work fine):

            class MyLabelWithOverlay : public QLabel
            {
            public:
                 MyLabelWithOverlay (QWidget * parent = NULL)
                       : QLabel(parent), overlayEnabled(false)
                 {
                 }
            
            public slots:
                 void enableOverlay(bool enabled)
                 {
                      overlayEnabled = enabled;
                 } 
            
            protected:
                 virtual void paintEvent(QPaintEvent * event)
                 {
                      QPixmap pix = pixmap();
                      qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
            
                      QTransform transform;
                      transform.scale(ratio, ratio);
            
                      QRect sourceRect = transform.mapRect(event->rect());
            
                      QPainter painter(this);
                      painter.drawPixmap(event->rect(), pix, sourceRect);
            
                      if (overlayEnabled)  {
                          // Draw your lines here
                      }
                 }
            
            private:
                 bool overlayEnabled;
            }
            

            You connect the QCheckBox's toggled(bool) signal to the enableOverlay(bool) slot and that's mostly it.

            EDIT: I've added the proper casting where the ratio is calculated.

            Kind regards.

            D Offline
            D Offline
            Donn
            wrote on 10 Mar 2016, 16:38 last edited by Donn 3 Oct 2016, 16:48
            #5

            @kshegunov

            I have created a header file

            #ifndef MYLABELWITHOVERLAY_H
            #define MYLABELWITHOVERLAY_H
            
            #include "QtGui"
            #include "QtCore"
            #include "QLabel"
            
            class MyLabelWithOverlay : public QLabel
            {
                Q_OBJECT
            
            public:
                 MyLabelWithOverlay (QWidget * parent = NULL);
            
            public slots:
                 void enableOverlay(bool enabled);
            
            protected:
                 virtual void paintEvent(QPaintEvent * event);
            
            private:
                 bool overlayEnabled;
            };
            
            
            #endif // MYLABELWITHOVERLAY_H
            
            

            and a source file

            #include "mylabelwithoverlay.h"
            
            MyLabelWithOverlay::MyLabelWithOverlay (QWidget * parent): QLabel(parent), overlayEnabled(false)
            {
            }
            
            void MyLabelWithOverlay::enableOverlay(bool enabled)
            {
                overlayEnabled = enabled;
            }
            
            
            void MyLabelWithOverlay::paintEvent(QPaintEvent * event)
            {
                QPixmap pix = QPixmap();
                qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
            
                QTransform transform;
                  transform.scale(ratio, ratio);
            
                QRect sourceRect = transform.mapRect(event->rect());
            
                QPainter painter(this);
                painter.drawPixmap(event->rect(), pix, sourceRect);
            
                if (overlayEnabled)  {
                    // Draw your lines here
                }
            }
            

            After that I promote QLabel widget in Designer to mylabelwithoverlay and try to run. I get the following errors in ui_mainwindow.h:

            C2143: syntax error: missing ';' before '*'
            
            C4430: missing type specifier - int assumed.
            
            

            Where could be the problem? I cannot edit ui_mainwindow.h file since it is auto generated. If I don't promote the widget the code compiles successfully after including mylabelwithoverlay.h file.

            EDIT: I have spelled the class name in lowercase only instead of MyLabelWithOverlay. Now it compiles fine but I cannot make any changes to this label.

            K 1 Reply Last reply 10 Mar 2016, 17:10
            0
            • D Donn
              10 Mar 2016, 16:38

              @kshegunov

              I have created a header file

              #ifndef MYLABELWITHOVERLAY_H
              #define MYLABELWITHOVERLAY_H
              
              #include "QtGui"
              #include "QtCore"
              #include "QLabel"
              
              class MyLabelWithOverlay : public QLabel
              {
                  Q_OBJECT
              
              public:
                   MyLabelWithOverlay (QWidget * parent = NULL);
              
              public slots:
                   void enableOverlay(bool enabled);
              
              protected:
                   virtual void paintEvent(QPaintEvent * event);
              
              private:
                   bool overlayEnabled;
              };
              
              
              #endif // MYLABELWITHOVERLAY_H
              
              

              and a source file

              #include "mylabelwithoverlay.h"
              
              MyLabelWithOverlay::MyLabelWithOverlay (QWidget * parent): QLabel(parent), overlayEnabled(false)
              {
              }
              
              void MyLabelWithOverlay::enableOverlay(bool enabled)
              {
                  overlayEnabled = enabled;
              }
              
              
              void MyLabelWithOverlay::paintEvent(QPaintEvent * event)
              {
                  QPixmap pix = QPixmap();
                  qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
              
                  QTransform transform;
                    transform.scale(ratio, ratio);
              
                  QRect sourceRect = transform.mapRect(event->rect());
              
                  QPainter painter(this);
                  painter.drawPixmap(event->rect(), pix, sourceRect);
              
                  if (overlayEnabled)  {
                      // Draw your lines here
                  }
              }
              

              After that I promote QLabel widget in Designer to mylabelwithoverlay and try to run. I get the following errors in ui_mainwindow.h:

              C2143: syntax error: missing ';' before '*'
              
              C4430: missing type specifier - int assumed.
              
              

              Where could be the problem? I cannot edit ui_mainwindow.h file since it is auto generated. If I don't promote the widget the code compiles successfully after including mylabelwithoverlay.h file.

              EDIT: I have spelled the class name in lowercase only instead of MyLabelWithOverlay. Now it compiles fine but I cannot make any changes to this label.

              K Offline
              K Offline
              kshegunov
              Moderators
              wrote on 10 Mar 2016, 17:10 last edited by
              #6

              @Donn
              Hello,
              Firstly, this QPixmap pix = QPixmap(); line is wrong. If you look at my example you'll see that the idea is not to create an empty pixmap but to get the image from the parent class' property. Secondly, I don't understand what changes you want to do with this label. You put your code that draws the lines, or whatsoever you wanted to draw, inside the if block (as indicated by the comment) and that's it. Did I misunderstand the problem in the first place?

              Kind regards.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • D Offline
                D Offline
                Donn
                wrote on 10 Mar 2016, 17:22 last edited by Donn 3 Oct 2016, 17:26
                #7

                For now I have promoted the QLabel widget label to MyLabelWithOverlay and I assume I can work with it as with a standard QLabel widget being able to change a text of this label, for example. Therefore, I tried to change the text by label->setText("lalal") but it doesn't work, no changes appear. Did I misunderstand something?

                P.S. So far I'm not trying to draw some lines but trying to understand how it works with this new label and I think I will do the rest when I get it. Of course, my goal is what you have described.

                K 1 Reply Last reply 10 Mar 2016, 17:28
                0
                • D Donn
                  10 Mar 2016, 17:22

                  For now I have promoted the QLabel widget label to MyLabelWithOverlay and I assume I can work with it as with a standard QLabel widget being able to change a text of this label, for example. Therefore, I tried to change the text by label->setText("lalal") but it doesn't work, no changes appear. Did I misunderstand something?

                  P.S. So far I'm not trying to draw some lines but trying to understand how it works with this new label and I think I will do the rest when I get it. Of course, my goal is what you have described.

                  K Offline
                  K Offline
                  kshegunov
                  Moderators
                  wrote on 10 Mar 2016, 17:28 last edited by kshegunov 3 Oct 2016, 17:29
                  #8

                  @Donn
                  Ah, I see. Well since this label of sorts is providing its own implementation of the painting, the parent class' painting method will not be invoked automatically. This means that if you want to see the text you set with label->setText("lalal") you'll have to paint it yourself in the void MyLabelWithOverlay::paintEvent(QPaintEvent * event) method. Does this clear it a bit? You could try setting a pixmap for the label (this should be displayed, although how well it's painted I can't vouch as I've written the example directly in the forum).

                  Kind regards.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  0
                  • D Offline
                    D Offline
                    Donn
                    wrote on 10 Mar 2016, 17:42 last edited by
                    #9

                    I'm still confused... Sorry for my stupid questions but I want to make it clear. I assume MyLabelWithOverlay inherits most of the methods provided by QLabel and I don't get why it cannot directly display text with label->setText() ?

                    K 1 Reply Last reply 10 Mar 2016, 17:45
                    0
                    • D Donn
                      10 Mar 2016, 17:42

                      I'm still confused... Sorry for my stupid questions but I want to make it clear. I assume MyLabelWithOverlay inherits most of the methods provided by QLabel and I don't get why it cannot directly display text with label->setText() ?

                      K Offline
                      K Offline
                      kshegunov
                      Moderators
                      wrote on 10 Mar 2016, 17:45 last edited by kshegunov 3 Oct 2016, 17:46
                      #10

                      @Donn
                      It inherits all of the methods provided by QLabel, but it overrides the QLabel::paintEvent method, so no painting is done from QLabel::paintEvent and consequently you don't get the text painted (which is what QLabel::paintEvent actually does).

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      0
                      • D Offline
                        D Offline
                        Donn
                        wrote on 10 Mar 2016, 17:50 last edited by
                        #11

                        So QLabel::paintEvent is actually responsible for painting a simple text and if I override it doesn't provide the functionality for displaying text anymore and I need to do it myself in the body of overridden function, right? Can you provide some code how it could be in the body because I don't have any idea.

                        K 1 Reply Last reply 10 Mar 2016, 17:59
                        0
                        • D Donn
                          10 Mar 2016, 17:50

                          So QLabel::paintEvent is actually responsible for painting a simple text and if I override it doesn't provide the functionality for displaying text anymore and I need to do it myself in the body of overridden function, right? Can you provide some code how it could be in the body because I don't have any idea.

                          K Offline
                          K Offline
                          kshegunov
                          Moderators
                          wrote on 10 Mar 2016, 17:59 last edited by
                          #12

                          @Donn said:

                          So QLabel::paintEvent is actually responsible for painting a simple text and if I override it doesn't provide the functionality for displaying text anymore and I need to do it myself in the body of overridden function, right?

                          Correct.

                          Can you provide some code how it could be in the body because I don't have any idea.

                          void MyLabelWithOverlay::paintEvent(QPaintEvent * event)
                          {
                              // This code draws the pixmap that was given with setPixmap(), and hopefully it does that correctly 
                              QPixmap pix = pixmap();
                              qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
                          
                              QTransform transform;
                              transform.scale(ratio, ratio);
                          
                              QRect sourceRect = transform.mapRect(event->rect());
                          
                              QPainter painter(this);
                              painter.drawPixmap(event->rect(), pix, sourceRect); //< Pixmap was drawn
                          
                              if (overlayEnabled)  {
                                  //< Here you can draw on top of that pixmap the lines (that's why it was left unfilled)
                              }
                          
                              // Here you can draw the text (on top of the pixmap and the lines
                              QRect widgetRect = rect(); //< This is the widget's rectangle
                              QString labelText = text(); //< This is the text that was set
                              // This following line draws the text centered horizontally and bound by the provided rectangle
                              painter.drawText(widgetRect, labelText, Qt::AlignHCenter); 
                          }
                          

                          Read and abide by the Qt Code of Conduct

                          jsulmJ 1 Reply Last reply 11 Mar 2016, 05:45
                          0
                          • D Offline
                            D Offline
                            Donn
                            wrote on 10 Mar 2016, 18:39 last edited by Donn 3 Oct 2016, 18:40
                            #13
                            void MyLabelWithOverlay::paintEvent(QPaintEvent * event)
                            {
                                const QPixmap pix = *pixmap();
                                qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
                            
                                QTransform transform;
                                  transform.scale(ratio, ratio);
                            
                                QRect sourceRect = transform.mapRect(event->rect());
                            
                                QPainter painter(this);
                                painter.drawPixmap(event->rect(), pix, sourceRect);
                            
                                if (overlayEnabled)  {
                                    // Draw your lines here
                                }
                                // Here you can draw the text (on top of the pixmap and the lines
                                QRectF widgetRect = rect(); //< This is the widget's rectangle
                                QString labelText = text(); //< This is the text that was set
                                // This following line draws the text centered horizontally and bound by the provided rectangle
                                //painter.drawText(widgetRect, labelText, Qt::AlignHCenter);
                            }
                            
                            

                            My app crashes after this saying that

                            QWidget::repaint: Recursive repaint detected
                            

                            If I uncomment the last line I get the following:

                            C2664: 'void QPainter::drawText(const QRectF &,const QString &,const QTextOption &)': cannot convert argument 1 from 'QRectF' to 'int'
                            
                            1 Reply Last reply
                            0
                            • K Offline
                              K Offline
                              kshegunov
                              Moderators
                              wrote on 10 Mar 2016, 21:07 last edited by kshegunov 3 Oct 2016, 21:12
                              #14
                              const QPixmap pix = *pixmap();
                              

                              Since you're not checking if the pointer returned is NULL, have you set a pixmap for the label with QLabel::setPixmap?
                              If you haven't this would cause a segfault, because dereferencing a NULL pointer isn't allowed.

                              Recursive repaint detected

                              This shouldn't be normally happening. Are you calling repaint() manually, or is there an explicit call to paintEvent() somewhere?

                              If I uncomment the last line I get the following: ... cannot convert argument 1 from 'QRectF' to 'int'

                              Have you included the header for QRectF?

                              Read and abide by the Qt Code of Conduct

                              D 1 Reply Last reply 11 Mar 2016, 06:26
                              0
                              • K kshegunov
                                10 Mar 2016, 17:59

                                @Donn said:

                                So QLabel::paintEvent is actually responsible for painting a simple text and if I override it doesn't provide the functionality for displaying text anymore and I need to do it myself in the body of overridden function, right?

                                Correct.

                                Can you provide some code how it could be in the body because I don't have any idea.

                                void MyLabelWithOverlay::paintEvent(QPaintEvent * event)
                                {
                                    // This code draws the pixmap that was given with setPixmap(), and hopefully it does that correctly 
                                    QPixmap pix = pixmap();
                                    qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
                                
                                    QTransform transform;
                                    transform.scale(ratio, ratio);
                                
                                    QRect sourceRect = transform.mapRect(event->rect());
                                
                                    QPainter painter(this);
                                    painter.drawPixmap(event->rect(), pix, sourceRect); //< Pixmap was drawn
                                
                                    if (overlayEnabled)  {
                                        //< Here you can draw on top of that pixmap the lines (that's why it was left unfilled)
                                    }
                                
                                    // Here you can draw the text (on top of the pixmap and the lines
                                    QRect widgetRect = rect(); //< This is the widget's rectangle
                                    QString labelText = text(); //< This is the text that was set
                                    // This following line draws the text centered horizontally and bound by the provided rectangle
                                    painter.drawText(widgetRect, labelText, Qt::AlignHCenter); 
                                }
                                
                                jsulmJ Offline
                                jsulmJ Offline
                                jsulm
                                Lifetime Qt Champion
                                wrote on 11 Mar 2016, 05:45 last edited by
                                #15

                                @kshegunov Wouldn't it be easier to first call QLabel::paintEvent(...) to get back the inherited functionality and then draw custom stuff?

                                https://forum.qt.io/topic/113070/qt-code-of-conduct

                                K 1 Reply Last reply 11 Mar 2016, 10:47
                                0
                                • K kshegunov
                                  10 Mar 2016, 21:07
                                  const QPixmap pix = *pixmap();
                                  

                                  Since you're not checking if the pointer returned is NULL, have you set a pixmap for the label with QLabel::setPixmap?
                                  If you haven't this would cause a segfault, because dereferencing a NULL pointer isn't allowed.

                                  Recursive repaint detected

                                  This shouldn't be normally happening. Are you calling repaint() manually, or is there an explicit call to paintEvent() somewhere?

                                  If I uncomment the last line I get the following: ... cannot convert argument 1 from 'QRectF' to 'int'

                                  Have you included the header for QRectF?

                                  D Offline
                                  D Offline
                                  Donn
                                  wrote on 11 Mar 2016, 06:26 last edited by
                                  #16

                                  @kshegunov said:

                                  Since you're not checking if the pointer returned is NULL, have you set a pixmap for the label with QLabel::setPixmap?
                                  If you haven't this would cause a segfault, because dereferencing a NULL pointer isn't allowed.

                                  Could you please provide a solution for this because I really don't get it how it is done since it is a big mess for me and trying to get it step by step. I really appreatiate your help!

                                  This shouldn't be normally happening. Are you calling repaint() manually, or is there an explicit call to paintEvent() somewhere?

                                  I do not call any repaint() or paintEvent() explicitly I think. I just simply created a header file and a source file as mentioned above and have included header file to other header file and have promoted one QLabel widget to MyLabelWithOverlay.

                                  Have you included the header for QRectF?

                                  I have included the header but it is still the same problem.

                                  1 Reply Last reply
                                  0
                                  • jsulmJ jsulm
                                    11 Mar 2016, 05:45

                                    @kshegunov Wouldn't it be easier to first call QLabel::paintEvent(...) to get back the inherited functionality and then draw custom stuff?

                                    K Offline
                                    K Offline
                                    kshegunov
                                    Moderators
                                    wrote on 11 Mar 2016, 10:47 last edited by
                                    #17

                                    @jsulm
                                    Absolutely! Although, I was half way down writing the code when I realized I had a QLabel instead of QWidget (which would be usually the case) and was reluctant to rewrite it. :)

                                    @Donn

                                    Could you please provide a solution for this because I really don't get it how it is done since it is a big mess for me and trying to get it step by step.

                                    Solution for what you mean? How to check whether a pointer is null? Simply check with if:

                                    QPixmap * pixmapPointer = pixmap();
                                    if (!pixmapPointer)
                                        return;
                                    
                                    QPixmap & pix = *pixmapPointer; //< You have to make sure pixmapPointer points to a valid object before using the deref operator (the *)
                                    

                                    Also something I noticed in your code is that you're passing const QPixmap * to QPainter::drawPixmap, which accepts const QPixmap &, you should fix that (look the snippet how conversion between the two is done).

                                    I have included the header but it is still the same problem.

                                    Usually this happens when the header is not present. Try passing the object directly:

                                    painter.drawText(QRectF(rect()), labelText, Qt::AlignHCenter);
                                    

                                    Read and abide by the Qt Code of Conduct

                                    D 1 Reply Last reply 11 Mar 2016, 11:21
                                    0
                                    • K kshegunov
                                      11 Mar 2016, 10:47

                                      @jsulm
                                      Absolutely! Although, I was half way down writing the code when I realized I had a QLabel instead of QWidget (which would be usually the case) and was reluctant to rewrite it. :)

                                      @Donn

                                      Could you please provide a solution for this because I really don't get it how it is done since it is a big mess for me and trying to get it step by step.

                                      Solution for what you mean? How to check whether a pointer is null? Simply check with if:

                                      QPixmap * pixmapPointer = pixmap();
                                      if (!pixmapPointer)
                                          return;
                                      
                                      QPixmap & pix = *pixmapPointer; //< You have to make sure pixmapPointer points to a valid object before using the deref operator (the *)
                                      

                                      Also something I noticed in your code is that you're passing const QPixmap * to QPainter::drawPixmap, which accepts const QPixmap &, you should fix that (look the snippet how conversion between the two is done).

                                      I have included the header but it is still the same problem.

                                      Usually this happens when the header is not present. Try passing the object directly:

                                      painter.drawText(QRectF(rect()), labelText, Qt::AlignHCenter);
                                      
                                      D Offline
                                      D Offline
                                      Donn
                                      wrote on 11 Mar 2016, 11:21 last edited by Donn 3 Nov 2016, 11:38
                                      #18

                                      @kshegunov

                                      Everything mentioned above compiles except the last problem:

                                      Usually this happens when the header is not present. Try passing the object directly:

                                      painter.drawText(QRectF(rect()), labelText, Qt::AlignHCenter);
                                      

                                      I still get the same error message. Instead I tried

                                      painter.drawText(20, 20, labelText);
                                      

                                      which compiles but I don't get any text displayed in the promoted MyLabelWithOverlay label.

                                      EDIT:

                                      Maybe I'm doing something wrong in other place. If you can, please check it because I have no idea what could be wrong. Perhaps somewhere I don't completely get how things work...

                                      mainwindow.h:

                                      #ifndef MAINWINDOW_H
                                      #define MAINWINDOW_H
                                      
                                      #include <QMainWindow>
                                      
                                      namespace Ui {
                                      class MainWindow;
                                      }
                                      
                                      class MainWindow : public QMainWindow
                                      {
                                          Q_OBJECT
                                      
                                      public:
                                          explicit MainWindow(QWidget *parent = 0);
                                          ~MainWindow();
                                      
                                      private:
                                          Ui::MainWindow *ui;
                                      };
                                      
                                      #endif // MAINWINDOW_H
                                      
                                      

                                      MainWindow.cpp:

                                      #include "mainwindow.h"
                                      #include "ui_mainwindow.h"
                                      #include "mylabelwithoverlay.h"
                                      
                                      MainWindow::MainWindow(QWidget *parent) :
                                          QMainWindow(parent),
                                          ui(new Ui::MainWindow)
                                      {
                                          ui->setupUi(this);
                                          ui->label_5->setText("hello world"); // label_5 is promoted to MyLabelWithOverlay
                                      }
                                      
                                      MainWindow::~MainWindow()
                                      {
                                          delete ui;
                                      }
                                      

                                      mylabelwithoverlay.h:

                                      #ifndef MYLABELWITHOVERLAY_H
                                      #define MYLABELWITHOVERLAY_H
                                      
                                      #include "QtGui"
                                      #include "QtCore"
                                      #include "QLabel"
                                      
                                      
                                      class MyLabelWithOverlay : public QLabel
                                      {
                                          Q_OBJECT
                                      
                                      public:
                                           MyLabelWithOverlay (QWidget * parent = NULL);
                                      
                                      public slots:
                                           void enableOverlay(bool enabled);
                                      
                                      protected:
                                           virtual void paintEvent(QPaintEvent * event);
                                      
                                      private:
                                           bool overlayEnabled;
                                      };
                                      
                                      
                                      #endif // MYLABELWITHOVERLAY_H
                                      
                                      

                                      MyLabelWithOverlay.cpp:

                                      #include "mylabelwithoverlay.h"
                                      #include <QRect>
                                      #include <QRectF>
                                      
                                      
                                      MyLabelWithOverlay::MyLabelWithOverlay (QWidget * parent): QLabel(parent), overlayEnabled(false)
                                      {
                                      }
                                      
                                      void MyLabelWithOverlay::enableOverlay(bool enabled)
                                      {
                                          overlayEnabled = enabled;
                                      }
                                      
                                      
                                      void MyLabelWithOverlay::paintEvent(QPaintEvent * event)
                                      {
                                          const QPixmap * pixmapPointer = pixmap();
                                          if (!pixmapPointer)
                                              return;
                                      
                                          const QPixmap & pix = *pixmapPointer;
                                      
                                          qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
                                      
                                          QTransform transform;
                                            transform.scale(ratio, ratio);
                                      
                                          QRect sourceRect = transform.mapRect(event->rect());
                                      
                                          QPainter painter(this);
                                          painter.drawPixmap(event->rect(), pix, sourceRect);
                                      
                                          if (overlayEnabled)  {
                                              // Draw your lines here
                                          }
                                          // Here you can draw the text (on top of the pixmap and the lines
                                          QRect widgetRect = rect(); //< This is the widget's rectangle
                                          QString labelText = text(); //< This is the text that was set
                                          // This following line draws the text centered horizontally and bound by the provided rectangle
                                          //painter.drawText(QRectF(rect()), labelText, Qt::AlignHCenter);
                                          painter.drawText(20, 20, labelText);
                                      
                                      }
                                      
                                      1 Reply Last reply
                                      0
                                      • K Offline
                                        K Offline
                                        kshegunov
                                        Moderators
                                        wrote on 11 Mar 2016, 11:54 last edited by
                                        #19

                                        @Donn
                                        You're not setting a pixmap for the label, so when the paint events gets executed pixmapPointer will be NULL and the function will return. If you wish to support both/either text and pixmap you have to enclose each in its own if block.

                                        void MyLabelWithOverlay::paintEvent(QPaintEvent * event)
                                        {
                                            QPainter painter(this);
                                        
                                            const QPixmap * pixmapPointer = pixmap();
                                            if (pixmapPointer)  {
                                                const QPixmap & pix = *pixmapPointer;
                                                qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
                                        
                                                QTransform transform;
                                                transform.scale(ratio, ratio);
                                        
                                                QRect sourceRect = transform.mapRect(event->rect());
                                                painter.drawPixmap(event->rect(), pix, sourceRect);
                                            }
                                        
                                            if (overlayEnabled)  {
                                                // Draw your lines here
                                            }
                                        
                                            QString labelText = text();
                                            if (!labelText.empty())  {
                                                painter.drawText(0, 0, labelText);
                                            }
                                        }
                                        

                                        Read and abide by the Qt Code of Conduct

                                        D 1 Reply Last reply 11 Mar 2016, 15:00
                                        0
                                        • K kshegunov
                                          11 Mar 2016, 11:54

                                          @Donn
                                          You're not setting a pixmap for the label, so when the paint events gets executed pixmapPointer will be NULL and the function will return. If you wish to support both/either text and pixmap you have to enclose each in its own if block.

                                          void MyLabelWithOverlay::paintEvent(QPaintEvent * event)
                                          {
                                              QPainter painter(this);
                                          
                                              const QPixmap * pixmapPointer = pixmap();
                                              if (pixmapPointer)  {
                                                  const QPixmap & pix = *pixmapPointer;
                                                  qreal ratio = qMin(static_cast<qreal>(width()) / pix.width(), static_cast<qreal>(height()) / pix.height());
                                          
                                                  QTransform transform;
                                                  transform.scale(ratio, ratio);
                                          
                                                  QRect sourceRect = transform.mapRect(event->rect());
                                                  painter.drawPixmap(event->rect(), pix, sourceRect);
                                              }
                                          
                                              if (overlayEnabled)  {
                                                  // Draw your lines here
                                              }
                                          
                                              QString labelText = text();
                                              if (!labelText.empty())  {
                                                  painter.drawText(0, 0, labelText);
                                              }
                                          }
                                          
                                          D Offline
                                          D Offline
                                          Donn
                                          wrote on 11 Mar 2016, 15:00 last edited by Donn 3 Nov 2016, 15:13
                                          #20

                                          @kshegunov

                                          I think I got it! I have included to the painterEvent the following:

                                          QPixmap pm(200, 200);
                                          pm.fill(Qt::white);
                                          setPixmap(pm);
                                          

                                          Now I can set the text from other class like:

                                          ui->label->setText("lala");
                                          

                                          However, I think I shouldn't set Pixmap inside paintEvent - better to do it in the other class so this type of label could be also used for other labels, right?

                                          EDIT:

                                          I liked the idea of @jsulm. Could you give me some hints how to achieve it? How to get the painting functionality from a standard QLabel and then add some additional my own painting?

                                          1 Reply Last reply
                                          0

                                          2/20

                                          10 Mar 2016, 14:01

                                          18 unread
                                          • Login

                                          • Login or register to search.
                                          2 out of 20
                                          • First post
                                            2/20
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved