0

Ok, so here's what I want to accomplish: I want to draw QImage so the window would have scroll bars in case of the image turned out to be too big. For now one, I have sth like this:

#include "imagewidget.h"
#include <QImage>
#include <QPainter>
#include <QGridLayout>
#include <QLabel>

ImageWidget::ImageWidget(QWidget* parent)
    : QWidget(parent)
{
    m_image = QImage();

    scrollArea = new QScrollArea(this);

    QGridLayout *gridLayout = new QGridLayout(this);
    imgDisplayLabel = new QLabel(this);
    imgDisplayLabel->setPixmap(QPixmap::fromImage(m_image));
    imgDisplayLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    imgDisplayLabel->setScaledContents(true);
    imgDisplayLabel->adjustSize();

    scrollArea->setWidget(imgDisplayLabel);

    gridLayout->addWidget(scrollArea,0,0);
    setLayout(gridLayout);

}

void ImageWidget::paintEvent(QPaintEvent* event)
{

    QPainter paint(this);
    if(!m_image.isNull())
        paint.drawImage(0,0, m_image);

    imgDisplayLabel->setPixmap(QPixmap::fromImage(m_image));
    imgDisplayLabel->adjustSize();
    imgDisplayLabel->setScaledContents(true);
}

void ImageWidget::setImage(QImage im)
{
    m_image = im;
    update();
}

void ImageWidget::removeImage()
{
    m_image = QImage();
    update();
}

However, it does not give me the effect that I want to have:

enter image description here

When I change QPainter paint(this); to QPainter paint(scrollArea); I have the error message (or, it's the warning I guess): QPainter::begin: Widget painting can only begin as a result of a paintEvent but I'm able to run the application, and open / close images. So, the program actually works with this, but it the error message bothers me and I would like to know how to get rid of it. With this only one changed line from the above src code app works and displays images as it should:

enter image description here

yak
  • 3,770
  • 19
  • 60
  • 111
  • 2
    You have to put an image into a label and label into a scroll area. No need to paint the image yourself. I don't see you do this in your code. You might take a look at the Qt example here: http://doc.qt.io/qt-5/qtwidgets-widgets-imageviewer-example.html – vahancho Jun 19 '15 at 12:01
  • @vahancho: thanks for the answer, I've aleady seen the example, but it did not help me. You wrote: `You have to put an image into a label and label into a scroll area. `, however, I did put the image into a label: `imgDisplayLabel = new QLabel(this); imgDisplayLabel->setPixmap(QPixmap::fromImage(m_image));` and set label into scroll area: `scrollArea->setWidget(imgDisplayLabel);`. However, I need the ImageWidget to be the Widget subclass, as well as I need the `paint` method (further in the code). – yak Jun 19 '15 at 12:51
  • You are painting in widget, which contains scroll area. You should actually paint in widget, which belongs to scroll area. `scrollArea->setWidget(imgWidget);` – Amartel Jun 19 '15 at 13:18
  • @Amartel: Nice, but I got: `no matching function for call to 'QScrollArea::setWidget(QImage&)'` – yak Jun 19 '15 at 15:55
  • Why are you bothering with `ImageWidget::paintEvent()`? If I understand your code, correctly, each time you wish to load a new image, you're loading it into `m_image`. Why don't you just set the `pixmap` of the label directly, at the time the image is loaded? Labels know how to paint themselves so, as soon as you load a new image, it will trigger it's own paint event and repaint itself. – RobbieE Jun 19 '15 at 18:15

1 Answers1

1

Question is, where do you want to paint: on ImageWidget, on imgDisplayLabel, or on scrollArea.

If I interpret correctly, the warning is basically saying that, if you want to begin a painter on a widget, you should do it in THE same widget's paint event.

In Qt 4.8 documentation

QPainter::QPainter(QPaintDevice * device)

Constructs a painter that begins painting the paint device immediately.

this means by calling the QPainter constructor with a target device, it begins immediately.

So, try hijacking the scroll area's paint event.

FYI, whenever you hijack a event in Qt, I recommend calling the base class's implementation first in you new implementation like this so the base class's behavior is preserved.

Community
  • 1
  • 1
user3528438
  • 2,737
  • 2
  • 23
  • 42
  • Can not do this (at least if I understand it correctly) because `paintEvent` in `QScrollArea` class is `protected`. – yak Jun 19 '15 at 15:54
  • 1
    @yak That's why I said `hijacking`, you need to sub class from the base class and overload its `paintEvent`. – user3528438 Jun 19 '15 at 16:15