PDA

View Full Version : QScrollView and repaint



munna
12th September 2006, 14:38
Hi,

I have reimplemented drawContents of QScrollView. I am drawing lots of stuff in this. When a window from some other application is dragged over to this and moved around, the drawing gets erased.

How can I prevent this ?

Thanks a lot

wysota
12th September 2006, 14:41
Maybe you reimplemented drawContents incorrectly? QScrollView should trigger a paint event (and eventually drawContents) after part of the widget gets obscured. Could you give more details, what exactly did you do?

munna
12th September 2006, 14:46
Here is my code :




void Paper::drawContents(QPainter *p, int cx, int cy, int cw, int ch)
{
QPixmap pm(cw, ch);
QPainter *pmp = new QPainter( &pm );
pmp->setBrush( white );
pmp->setPen( NoPen );
pmp->drawRect( 0, 0, cw, ch);
pmp->setPen( black );
pmp->translate( -cx, -cy );

//My drawing code. Everything is done useing pmp

pmp->end();
p->drawPixmap( cx, cy, pm );
p->end();
delete pmp;
}



Thanks a lot

wysota
12th September 2006, 14:53
I think the translation might be messing the things up (I think the code is incorrect). Try getting rid of the pixmap at all and draw the whole viewport directly. If it helps, you can then optimise some things to get better results.

munna
12th September 2006, 15:03
Here is the new code :




void Paper::drawContents(QPainter *pmp, int cx, int cy, int cw, int ch)
{
//QPixmap pm(cw, ch);
//QPainter *pmp = new QPainter( &pm );
pmp->setBrush( white );
pmp->setPen( NoPen );
pmp->drawRect( 0, 0, cw, ch);
//pmp->setPen( black );
//pmp->translate( -cx, -cy );

//My drawing code
}



It did not solve the first problem. Also, now flickering is introduced.
Does this has to do something with contentsHeight and contentsWidth ?

Thanks a lot for your time

wysota
12th September 2006, 15:30
How about:


void Paper::drawContents(QPainter *pmp, int cx, int cy, int cw, int ch)
{
pmp->setClipRect(cx,cy,cw,ch);
pmp->setClipping(true);
pmp->fill(Qt::white);
//Your drawing code
}

munna
12th September 2006, 15:40
It does not work.

Also, if I do not translate, and when scrollbars appear, all the drawing is messed up.

Please Help
Thanks a lot

wysota
12th September 2006, 15:44
It should work. Did you reimplement some other methods too? Maybe the viewport isn't set up correctly?

munna
12th September 2006, 17:18
Here is the list of all the methods that I have reimplemented.




virtual void drawContents(QPainter *p, int cx, int cy, int cw, int ch);
virtual void keyPressEvent(QKeyEvent *);
virtual void contentsMousePressEvent(QMouseEvent *);
virtual void contentsMouseDoubleClickEvent(QMouseEvent *);
virtual void contentsMouseReleaseEvent(QMouseEvent *);
virtual void contentsMouseMoveEvent(QMouseEvent *);
virtual void focusInEvent(QFocusEvent *);
virtual void resizeEvent(QResizeEvent *);



Also, can you please explain why you think your code should work ?

Thanks a lot.

wysota
12th September 2006, 17:32
Because drawContents should work on the viewport, meaning that you shouldn't need to translate the painter if the viewport was set up correctly -- you draw directly on the viewport. How did you initialise the viewport?

munna
12th September 2006, 17:44
In the constructor I have :




viewport()->setBackgroundMode( Qt::NoBackground ); viewport()->setFocusPolicy(QWidget::StrongFocus);



Apart from the above two lines, I dont do much with the viewport. I only use resizeContents according to the size of my drawing and then call repaint().

Can you please explain this a little more? All this while I thought I was doing the write thing.

Thanks a lot

wysota
12th September 2006, 17:46
This seems to work (more or less):


#include <qapplication.h>
#include <qscrollview.h>
#include <qpainter.h>

class Test : public QScrollView{
public:
Test() : QScrollView(){ resizeContents(600, 300); }
~Test(){}
protected:
void drawContents(QPainter *p, int cx, int cy, int cw, int ch){
// p->setClipRect(cx,cy,cw,ch);
// p->setClipping(true);
p->fillRect(0,0,600,300, Qt::white);
p->setPen(Qt::red);
p->drawLine(0,0, 600, 300);
}
};

int main(int argc, char **argv){
QApplication app(argc, argv);
Test t;
t.resize(200, 100);
t.show();
app.setMainWidget(&t);
return app.exec();
}

When clipping is enabled, the widget is not refreshed correctly though...

munna
12th September 2006, 17:59
Can you please do me a favor ?

Can you try it with the following code ? It should draw red horizontal lines, right ?

[CODE]

void drawContents(QPainter *p, int cx, int cy, int cw, int ch)
{
//p->setClipRect(cx,cy,cw,ch);
// p->setClipping(true);
p->fillRect(0,0,600,300, Qt::white);
p->setPen(Qt::red);
for(int i = 0; i < 300; i+=25){
p->drawLine(0,i, 600, i);
}
}

[CODE]

Once you have the drawing, resize your browser( or any other window) and move it around this drawing.

Are the lines getting drawn as the new area is shown and the window is moved ?

Thanks a lot.

wysota
12th September 2006, 18:18
No, they don't.

munna
12th September 2006, 18:23
Shouldn't the lines be drawn as I move the window ? I mean, shouldn't the drawContents be called and the drawing should be updated?

Now, since we know that drawContents is not called, is there a way be which I can detect this and call repaint()

Thanks a lot for your time.
Thanks a lot

munna
13th September 2006, 07:17
Any ideas on this one ?

Thanks.

wysota
13th September 2006, 10:20
A simple way around this is to add a child widget to the scrollview and do all the drawing in the paint event of the widget.


class MyWidget : public QWidget{
public:
MyWidget(QWidget *parent = 0) : QWidget(parent){}
protected:
void paintEvent(QPaintEvent *pe){
//...
}
};
//...
wid = new MyWidget(viewport());
wid.resize(600, 400);
//...