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
Forum Updated to NodeBB v4.3 + New Features

QPaintEvent in MainWindow

Scheduled Pinned Locked Moved Unsolved General and Desktop
qprinteventqprinterqmainwindow
20 Posts 4 Posters 11.6k Views 2 Watching
  • 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.
  • DonnD Offline
    DonnD Offline
    Donn
    wrote on 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() ?

    kshegunovK 1 Reply Last reply
    0
    • DonnD Donn

      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() ?

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by kshegunov
      #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
      • DonnD Offline
        DonnD Offline
        Donn
        wrote on 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.

        kshegunovK 1 Reply Last reply
        0
        • DonnD Donn

          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.

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on 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
          0
          • DonnD Offline
            DonnD Offline
            Donn
            wrote on last edited by Donn
            #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
            • kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by kshegunov
              #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

              DonnD 1 Reply Last reply
              0
              • kshegunovK kshegunov

                @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 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

                kshegunovK 1 Reply Last reply
                0
                • kshegunovK kshegunov
                  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?

                  DonnD Offline
                  DonnD Offline
                  Donn
                  wrote on 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

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

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on 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

                    DonnD 1 Reply Last reply
                    0
                    • kshegunovK kshegunov

                      @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);
                      
                      DonnD Offline
                      DonnD Offline
                      Donn
                      wrote on last edited by Donn
                      #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
                      • kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on 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

                        DonnD 1 Reply Last reply
                        0
                        • kshegunovK kshegunov

                          @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);
                              }
                          }
                          
                          DonnD Offline
                          DonnD Offline
                          Donn
                          wrote on last edited by Donn
                          #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

                          • Login

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