paintEvent is not painting complete objects
-
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_OBJECTpublic:
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?
-
@NIXIN
you are doing multiple mistakes in your code.- you are creating widgets on every paintEvent call! This is very bad design.
- 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.
-
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.
-
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();
}
-
@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() -
@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 ); }
-
Perhaps this might be also useful?
-
@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.