PDA

View Full Version : Scrolling in scaled Painter area causes lack of re-painting



sdzell18
27th January 2012, 17:06
Hi Everyone.
I have taken the Scribble Example from Qt 4.8 and done some modifications to it in hope to later do it to my own, similar project. For those of you not familar with the Scribble Example it lets you draw, basically like the pencil tool in windows paint.

Anyway, have used QScrollArea to make the window scrollable which works fine when the scribbleArea is at a its original scale (1.0).
I increased the scale, to enlarge the graphics using the QPainter::scale() function and change the scale to 1.25. When I scroll at this new scale the window gets lines like the widget is not re-painting properly until I use the pencil again at which point the lines go away and the scribbleArea looks normal again.

7329
Notice the lines on the top and left side of the white scribbleArea.

Here is what I have modified to achieve this:
the ScribbleArea:: paintEvent() function for scaling

void ScribbleArea::paintEvent(QPaintEvent *event)
//! [13] //! [14]
{
QPainter painter(this);

painter.scale(1.25, 1.25); //ADDED LINE FOR SCALING

QRect dirtyRect = event->rect();
painter.drawImage(dirtyRect, image, dirtyRect);

}

The ScribbleArea::drawLineTo() function to make it update the whole scribble area rather than just a small section

void ScribbleArea::drawLineTo(const QPoint &endPoint)
//! [17] //! [18]
{
QPainter painter(&image);
painter.setPen(QPen(myPenColor, myPenWidth, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin));
painter.drawLine(lastPoint, endPoint);
modified = true;

//int rad = (myPenWidth / 2) + 2;
//update(QRect(lastPoint, endPoint).normalized()
// .adjusted(-rad, -rad, +rad, +rad));
update(); //ADDED LINE
lastPoint = endPoint;
}


In the MainWindow constructor I added QScrollArea widget

MainWindow::MainWindow()
{
scribbleArea = new ScribbleArea;
scribbleArea->setMaximumHeight(500);
scribbleArea->setMaximumWidth(500);
scribbleArea->setMinimumSize(500, 500);
//setCentralWidget(scribbleArea);

scrollArea = new QScrollArea;
scrollArea->setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOn );
scrollArea->setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOn );
scrollArea->setWidget(scribbleArea);

setCentralWidget(scrollArea);

createActions();
createMenus();

setWindowTitle(tr("Scribble"));
resize(500, 500);
}

All other code is unchanged from the original example. Does anyone know what could be causing this?
Scribble example documentation here: http://developer.qt.nokia.com/doc/qt-4.8/widgets-scribble.html

Spitfire
31st January 2012, 16:08
Connect both scroll bars (scrollArea->[horizontal/vertical]Scrollbar()) valueChanged() signal to scribble area update() slot or in scribble area paint event use image.rect() instead of dirtyRect.
In fact both approaches do the same - they repaint whole image instead of only dirty rectangle.
This tells you that dirty rectangle is wrong.

sdzell18
31st January 2012, 16:20
Thank you, Thank you, Thank you! Using image.rect() for the dirtyRect worked perfectly.

Spitfire
31st January 2012, 16:41
Remember that always using whole image is not as efficient as drawing only required part of it.

sdzell18
31st January 2012, 16:54
Yes I will keep that in mind

xfreax
1st February 2012, 10:41
Hi Spitfire and sdzell18,

I am working on Qt 4.8 running on Linux (Ubuntu).
Incidentally I have been doing this stuff to scroll the image using scrollBars.

But recently I tried to implement Kinetic scrolling on the image where we paint, instead of doing all the physics from the scratch, using Flick Charm (http://labs.qt.nokia.com/2008/11/15/flick-list-or-kinetic-scrolling/), QsKineticScroll (http://www.developer.nokia.com/Community/Wiki/Qt_Kinetic_scrolling_-_from_idea_to_implementation)

As you may know, the mouseEvents on Scribble has to be sent to the ScrollArea when some mouseMove with dx of +15 && -15 pixels on the vertical direction is made while scrolling. I did ignore() in the Scribble's mouseMove and mouseRelease if the condition (dx allowance) was satisfied, but was not able to get the image to kinetically scroll.

Can you give some idea/hint how this can be implemented? If the FlickCharm or QsKineticScroll isnt necessary, can we do this by inheriting QAbstractScrollArea properties?

Thanks!

Spitfire
1st February 2012, 16:30
First - I would suggest starting new thread rather than piggybacking on remotley related topic.
Maybe some moderator can split it?

Second - You can achieve what you want probably in many ways. As you said that you don't want to do everything from a scratch then Flick Charm or any other ready-made solution is the way to go.

After quick look at the documentation of QsKineticScroll one thing looks like a starting point:

When installing the event filter, the important thing to notice is that it has to be installed for both the scroll area and its viewport. A scroll area is not a single item, and failing to install the filter on the viewport will result in not getting any mouse events at all.

As I haven't used any of those so I can't tell why it doesn't work, it's even more difficult without any code from your side.

Please, take the extra mile and provide compilable example of your problem. Much more likely you'll get solution for your problem.