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

paintEvent is not painting complete objects

Scheduled Pinned Locked Moved Unsolved General and Desktop
qpainterqpaintevent
11 Posts 4 Posters 6.0k 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.
  • 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