QWidget unwanted paintEvent



  • Hi all,

    I have a QDialog with some child: a QWidget (subclassed in MyWidget) and a QLabel .

    The MyWidget has a custom paintEvent :

    @

    void MyWidget::paintEvent(QPaintEvent *event)
    {
    QPainter p(this);
    p.drawImage(0,0,image);
    }
    @

    Image is a big QImage so drawing the image is slow.

    My problem is that if the QLabel text or its state (enabled, disabled) change it always automatically execute MyWidget::paintEvent taking a lot of time.
    I only want manually call update to draw a new image.
    How can I avoid this?

    Thanks



  • Hello Luca,

    What exactly are you trying to do? Perhaps there is another way to resolve your problem.



  • [quote author="iunknwn" date="1282750845"]Hello Luca,

    What exactly are you trying to do? Perhaps there is another way to resolve your problem.[/quote]

    Hi iunknwn,
    the application is a kind of SCADA system that generate an image from an svg changing some svg object according on the state of something.

    The application must run on the beagleboard (linux embedded) and the problem is that "drawing" an image on a QWidget is slow in that board.

    Near the QWidget there is a QLabel that change its text frequently and every text change it generate an "update()" on the QWidget.



  • Look into QPaintEvent::Region().

    From the doc:

    "Many widgets can simply repaint their entire surface when asked to, but some slow widgets need to optimize by painting only the requested region: QPaintEvent::region()."

    Alternately, if only label is changing and not the QImage, you can pass additional 4 agruments (sx, sy, sw, sh) to drawImage and specify only part of image to be re-drawn. Look into QPainter::drawImage() documentation.



  • Thanks,

    but I need to avoid the update() when don't needed also because Qt clear the QWidget before calling paintEvent and if I draw only a part of the image I can't see the other part.



  • wait a minute. Why do you even need to make a custom widget and go through painting if all you have is a QImage and a QLabel. Why not make both a child of a QWidget and put them in a layout?

    @class MyWidget : public QWidget

    {

    Q_OBJECT

    private:

    QLabel* lbl;

    QImage* img;

    public:

    MyWidget(QWidget* parent = 0) {

    lbl = new QLabel();
    img = new QImage();

    QVBoxLayout* layout = new QVBoxLayout();

    layout->addWidget(lbl);

    layout->addWidget(img);

    setLayout(layout);
    }

    }
    @

    Am I missing anything?



  • I finally found this:
    @
    Qt::WA_OpaquePaintEvent

    Indicates that the widget paints all its pixels when it receives a paint event. Thus, it is not required for operations like updating, resizing, scrolling and focus changes to erase the widget before generating paint events. The use of WA_OpaquePaintEvent provides a small optimization by helping to reduce flicker on systems that do not support double buffering and avoiding computational cycles necessary to erase the background prior to painting. Note: Unlike WA_NoSystemBackground, WA_OpaquePaintEvent makes an effort to avoid transparent window backgrounds. This flag is set or cleared by the widget's author.
    @

    So I put:

    setAttribute(Qt::WA_OpaquePaintEvent);

    in MyWidget constructor to avoid erasing the widget before paintEvent and in paintEvent I put:
    @
    void MyWidget::paintEvent(QPaintEvent *event)
    {
    if(update_required)
    {
    QPainter p(this);
    p.drawImage(0,0,image);
    }
    }
    @

    This way I can avoid the unwanted drawImage.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.