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