PDA

View Full Version : How to draw in a QScrollArea?



yannwilfried
1st September 2013, 21:25
Hi,

I have a classed that inherits QWidget. Inside of it, I have a QScrollArea with some QLabel items wrapped in a QGridLayout. Since I want to connect my labels through lines, I reimplemented the method paintEvent(QPaintEvent *) (http://qt-project.org/doc/qt-4.8/qwidget.html#paintEvent). I unfortunately have the problem that the drawing occurs outside the scroll area as you can see in the attached image. Any hints?

Thanks.

high_flyer
2nd September 2013, 09:43
Looks like you are painting in the widget containing the scroll-area and not in the scroll area widget.
Why don't you put your labels in to a widget, do all the special stuff on that widget, and put that widget as content widget for the scroll area?

yannwilfried
2nd September 2013, 10:08
You're completely right. I just can't figure out why? I subclassed QWidget and setup the UI like the following:


void PaintEventInScrollArea::setupUi()
{
QGridLayout *gridLayout = new QGridLayout;

for (int i = 0; i < inputCount; ++i) {
inputLabel = new QLabel(QString("Input %1").arg(i + 1));
inputLabel->setMargin(60);
gridLayout->addWidget(inputLabel, i + 1, 0);
}

for (int i = 0; i < outputCount; ++i) {
outputLabel = new QLabel(QString("Output %1").arg(i + 1));
outputLabel->setMargin(60);
gridLayout->addWidget(outputLabel, 0, i + 1);
}

for (int i = 0; i < inputCount; ++i) {
for (int j = 0; j < outputCount; ++j) {
connectionLabel = new QLabel(QString("Connect %1").arg(j + 1));
connectionLabel->setFixedHeight(20);
connectionLabel->setMargin(60);
connectionLabel->setFrameStyle(QFrame::Box);
connectionLabel->setAlignment(Qt::AlignCenter);
gridLayout->addWidget(connectionLabel, i + 1, j + 1);
}
}

QWidget *viewport = new QWidget;
viewport->setLayout(gridLayout);

QScrollArea *scrollArea = new QScrollArea;
//scrollArea->setFrameShape(QFrame::NoFrame);
scrollArea->setWidget(viewport);

QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::LeftToRight);
mainLayout->addWidget(scrollArea);
this->setLayout(mainLayout);
}
and reimplement paintEvent. A simple working example looks like


void PaintEventInScrollArea::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::darkRed);
QRectF rectangle(10.0, 20.0, 80.0, 60.0);
painter.drawRect(rectangle);
}


If my painter take as parent the widget inside the scroll area, I get the error


paint device returned engine == 0

I think I will subclass QAbstractScrollArea and insert my widget inside it.

high_flyer
2nd September 2013, 10:45
You're completely right. I just can't figure out why?
Why what? your are painting in the upper parent widget!
Your upper parent widget IS PaintEventInScrollArea.
You put in to it a QSrollArea and a QWidget.
And its in the QWidget where you should paint, not in PaintEventInScrollArea which is the upper one!
Subclass your QWidget (the one you put in to your QScrollArea, the one your call 'viewport ') and overload it's paintEvent().

yannwilfried
3rd September 2013, 09:46
Fine. I simply left the widget as it was and later wrap the whole stuff as you suggested in a QScrollArea with the method setWidget().