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. paintEvent is not painting complete objects
QtWS25 Last Chance

paintEvent is not painting complete objects

Scheduled Pinned Locked Moved Unsolved General and Desktop
qpainterqpaintevent
11 Posts 4 Posters 6.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.
  • N NIXIN
    5 Sept 2016, 06:26

    I am trying this piece of code below:

    widget.h

    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QWidget>
    #include <QLabel>
    #include <QPainter>

    namespace Ui {
    class Widget;
    }

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    void paintEvent(QPaintEvent *e);
    void operation();
    void drawLabel();
    
    int flag = 0;
    int startX, startY;
    QString labelText;
    

    private:
    Ui::Widget *ui;
    };

    #endif // WIDGET_H

    widget.cpp

    #include "widget.h"
    #include "ui_widget.h"

    Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
    {
    ui->setupUi(this);
    }

    Widget::~Widget()
    {
    delete ui;
    }

    void Widget::paintEvent(QPaintEvent *e)
    {
    QPainter *painter = new QPainter(this);
    if(flag == 1)
    {
    painter->setPen(QPen(Qt::black, 1));
    painter->drawLine(startX, startY, startX+30, startY);
    painter->drawLine(startX+50, startY, startX+80, startY);
    drawLabel();
    }
    }

    void Widget::drawLabel()
    {
    QLabel *label = new QLabel(this);
    label->setStyleSheet("border: 1px solid black");
    label->setGeometry(startX+30, startY-10, 20, 20);
    label->setText(labelText);
    label->show();
    }

    void Widget::operation()
    {
    int found = 1;

    if(found)
    {
        labelText = "2";
        startX = 20;
        startY = 50;
        flag = 1;
        update();
    
        labelText = "3";
        startX = 100;
        startY = 50;
        flag = 1;
        update();
    }
    

    }

    main.cpp

    #include "widget.h"
    #include <QApplication>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Widget w;
    w.operation();
    w.show();

    return a.exec();
    

    }

    I want to draw a label between two lines side by side, but when I run the above code label with labelText 3, between two lines is visible. labelText 2, between two lines is not painted. I don,t understand why? Can anybody help me to solve this?

    R Offline
    R Offline
    raven-worx
    Moderators
    wrote on 5 Sept 2016, 06:37 last edited by raven-worx 9 May 2016, 06:39
    #2

    @NIXIN
    you are doing multiple mistakes in your code.

    1. you are creating widgets on every paintEvent call! This is very bad design.
    2. in your Widget::operation() you update your data and call update() to immediately set the data again and call update() again. You should know that update() schedules a paint-event, where multiple calls to update() still result in a single paint-event (in the next event loop iteration). So it doesn't repaint immediately. There is a repaint() method for this, but as i said you already have a bad design by creating widgets on every paintEvent call.

    You should draw the text using QPainter instead creating a QLabel every time. But still the label text "2" would never be rendered, since you immediately overwrite it afterwards.

    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
    If you have a question please use the forum so others can benefit from the solution in the future

    1 Reply Last reply
    0
    • N Offline
      N Offline
      NIXIN
      wrote on 5 Sept 2016, 06:42 last edited by
      #3

      can you provide a small piece of code, how to do it?

      R 1 Reply Last reply 5 Sept 2016, 06:50
      0
      • N NIXIN
        5 Sept 2016, 06:42

        can you provide a small piece of code, how to do it?

        R Offline
        R Offline
        raven-worx
        Moderators
        wrote on 5 Sept 2016, 06:50 last edited by raven-worx 9 May 2016, 06:51
        #4

        @NIXIN

        void Widget::paintEvent(QPaintEvent *e)
        {
            QPainter painter(this);  // do create the painter on the stack
            ....
            drawLabel( p );
        }
        
        void Widget::drawLabel(QPainter & p)
        {
        QRect rect(startX+30, startY-10, 20, 20);
        p.setPen( QPen::QPen(Qt::black, 1.0, Qt::SolidLine) );
        p.setBrush( Qtt::NoBrush );
        p.drawRect( rect );
        p.drawText( rect, Qt::AlignCenter, labelText );
        }
        

        But as i said, this only draws the last label text set. You should store your data (position, label text,...) in a list (and call update() once). And draw each using drawLabel() for example.

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        1 Reply Last reply
        1
        • N Offline
          N Offline
          NIXIN
          wrote on 5 Sept 2016, 06:54 last edited by
          #5

          That's fine, what I want to know is how to not delete the drawing from previous paintevent,
          because as per your statement:
          " But still the label text "2" would never be rendered, since you immediately overwrite it afterwards."
          I want to keep the drawing for both:

          if(found)
          {
          labelText = "2";
          startX = 20;
          startY = 50;
          flag = 1;
          update();

          labelText = "3";
          startX = 100;
          startY = 50;
          flag = 1;
          update();
          

          }

          R 1 Reply Last reply 5 Sept 2016, 06:55
          0
          • N NIXIN
            5 Sept 2016, 06:54

            That's fine, what I want to know is how to not delete the drawing from previous paintevent,
            because as per your statement:
            " But still the label text "2" would never be rendered, since you immediately overwrite it afterwards."
            I want to keep the drawing for both:

            if(found)
            {
            labelText = "2";
            startX = 20;
            startY = 50;
            flag = 1;
            update();

            labelText = "3";
            startX = 100;
            startY = 50;
            flag = 1;
            update();
            

            }

            R Offline
            R Offline
            raven-worx
            Moderators
            wrote on 5 Sept 2016, 06:55 last edited by
            #6

            @NIXIN
            as i said store your data (e.g. struct) in a list and draw each item separately while iterating over the list in the paintEvent()

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            0
            • N Offline
              N Offline
              NIXIN
              wrote on 5 Sept 2016, 07:00 last edited by
              #7

              Can you please provide a small code

              R 1 Reply Last reply 5 Sept 2016, 07:12
              0
              • N NIXIN
                5 Sept 2016, 07:00

                Can you please provide a small code

                R Offline
                R Offline
                raven-worx
                Moderators
                wrote on 5 Sept 2016, 07:12 last edited by
                #8

                @NIXIN
                come on thats not that hard...

                struct Data {
                    Data(QString t, int x, int y, int f)
                         : labelText(t), startX(x), startY(y), flag(f)
                    {
                    }
                
                    QString labelText;;
                    int startX;;
                    int startY;
                    int flag;
                }
                QList<Data> dataList;
                ...
                void Widget::operation()
                {
                int found = 1;
                
                if(found)
                {
                    dataList.clear();
                
                    dataList << Data("2", 20, 50, 1);
                    dataList << Data("3", 100, 50, 1);
                    update();
                }
                
                }
                
                void Widget::paintEvent(QPaintEvent *e)
                {
                    QPainter painter(this);  // do create the painter on the stack
                    ....
                    foreach( Data d, dataList )
                         drawLabel( p, data );
                }
                
                void Widget::drawLabel(QPainter & p, const Data & d)
                {
                QRect rect(d.startX+30, d.startY-10, 20, 20);
                p.setPen( QPen::QPen(Qt::black, 1.0, Qt::SolidLine) );
                p.setBrush( Qt::NoBrush );
                p.drawRect( rect );
                p.drawText( rect, Qt::AlignCenter, d.labelText );
                }
                

                --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                If you have a question please use the forum so others can benefit from the solution in the future

                1 Reply Last reply
                3
                • J Offline
                  J Offline
                  Jan-Willem
                  wrote on 5 Sept 2016, 07:39 last edited by
                  #9

                  Perhaps this might be also useful?

                  http://www.cplusplus.com/doc/tutorial/structures/

                  http://doc.qt.io/qt-5/qlist.html

                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    VRonin
                    wrote on 5 Sept 2016, 09:08 last edited by
                    #10

                    How about composing the widget instead of painting it.
                    Put two QFrame with a HLine style and a label in a QVBoxLayout. So much easier!

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    J 1 Reply Last reply 5 Sept 2016, 09:41
                    0
                    • V VRonin
                      5 Sept 2016, 09:08

                      How about composing the widget instead of painting it.
                      Put two QFrame with a HLine style and a label in a QVBoxLayout. So much easier!

                      J Offline
                      J Offline
                      Jan-Willem
                      wrote on 5 Sept 2016, 09:41 last edited by
                      #11

                      @VRonin Depends on what he wants to achieve.
                      Is it a widget, than I agree with you.
                      Is it some CAD-drawing (looks like a diagram symbol to me), then I would prefer drawing.
                      For the latter the Graphics View Framework would be more practical though.

                      1 Reply Last reply
                      0

                      11/11

                      5 Sept 2016, 09:41

                      • Login

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