PDA

View Full Version : Performance problems with overlapping qgraphicsitems



brjames
5th February 2007, 23:54
I have an application where I've got 4 different types of QGraphicsItems. In the normal case, all 4 of these items have the exact same center.

One is an unfilled circle with diameter 10.

One is a cross that touches the midpoints of a 10x10 square

One is an 'X' that touches the corners of a 10x10 square.

The last is a filled in 3x3 square.

I am experiencing much slowdown and %100 CPU utilization. I've looked at making sure boundingRect and shape return exact shape, but in the normal case, they do all collide. Is there anything I can do to increase performance?

Or should this not be a problem and there is something else that might be causing my performance problem?

Thanks!

aamer4yu
6th February 2007, 04:02
There must be something else thats causing the problem.
You can add thousands of graphics items without any noticable slowdown.

You might be leaking memory somewhere , or processing something infinitely.

Gopala Krishna
6th February 2007, 05:13
I am experiencing much slowdown and %100 CPU utilization. I've looked at making sure boundingRect and shape return exact shape, but in the normal case, they do all collide. Is there anything I can do to increase performance?

Or should this not be a problem and there is something else that might be causing my performance problem?

Thanks!

As aamer pointed out there must be some other problem. Can you show some code ?
Also have you tried the chip demo shipped by qt ? I ask this because it manages 40000 items(also proved to perform well for 2 million items) in 4 views which works well even on my low end comp. Do you experience slow down in demo ?

cyrba
24th February 2007, 16:57
Hello, i eperimented performances problem with graphicsview and
found a workaround wich can perhaps help,
try it, it is very easy, you only have to reimplement paintEvent function like this
in a subclass :


class MyFasterGraphicView :public QGraphicsView
{
Q_OBJECT
public:
MyFasterGraphicView( ...);
protected:
...
void paintEvent ( QPaintEvent * event );
...
};

void MyFasterGraphicView::paintEvent ( QPaintEvent * event )
{
QPaintEvent *newEvent=new QPaintEvent(event->region().boundingRect());
QGraphicsView::paintEvent(newEvent);
delete newEvent;
}

I can explain the reason, is someone is interrested,

Have fun,

CyrBa

Gopala Krishna
3rd June 2007, 07:17
Hello, i eperimented performances problem with graphicsview and
found a workaround wich can perhaps help,
try it, it is very easy, you only have to reimplement paintEvent function like this
in a subclass :


class MyFasterGraphicView :public QGraphicsView
{
Q_OBJECT
public:
MyFasterGraphicView( ...);
protected:
...
void paintEvent ( QPaintEvent * event );
...
};

void MyFasterGraphicView::paintEvent ( QPaintEvent * event )
{
QPaintEvent *newEvent=new QPaintEvent(event->region().boundingRect());
QGraphicsView::paintEvent(newEvent);
delete newEvent;
}

I can explain the reason, is someone is interrested,

Have fun,

CyrBa

Indeed the performance is better. Can somebody explain how this improves?

stevel
29th April 2008, 18:24
I was having the same problem. A fairly simple GraphicsView with ellipses and rects and so forth, where if I put more then about 10-20 items on the view it was very slow, and used 90% of the CPU. When I made the change above, things are working much better.

If someone could please explain why I was seeing such slow behavior, and why this change helps, I would really appreciate it.

Also it there something I could do to speed things up otherwise I would like to know about that as well.

Is the difference between my project and 40,000 chips just the fact that in my project some of the GraphicsItems can overlap?

wysota
29th April 2008, 22:22
It's hard to say without seeing the actual code. My guess is that you should play a bit with different update modes of QGraphicsView or improve your bounding rect implementation.

stevel
29th April 2008, 22:51
One question I had was why is this code helping, and after looking at the code again, it seems that all it is doing is replacing the paintEvent with a generic paint event that has default settings except for the boundingRect. This means that one of the properties of the paint event must have been responsible for the slow down. I will put a breakpoint into the method, and compare the events. This might give me a hint as to what is wrong.

Here's the code I use to create my view:



worksheetScene = new(QGraphicsScene);
worksheetView = new(QWorksheetView);

// JSL - single sceneDrawCommon for common drawObject behavior
sceneDrawCommon = new QDrawCommon();
worksheetScene->addItem(sceneDrawCommon);

worksheetView->setViewportUpdateMode(QGraphicsView::SmartViewport Update);
worksheetView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
worksheetView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );
worksheetView->setScene(worksheetScene);
worksheetView->setDragMode(QGraphicsView::RubberBandDrag);
worksheetView->setAcceptDrops(true);
worksheetView->show();
setWidget(worksheetView);

stevel
30th April 2008, 00:00
I seem to be getting multiple paintEvents infinitely whether there are any changes or not. I looked for an update call in my paint code, but didn't see one. Interestingly this only happens when I have at least one GraphicsItem in the view. When I have none, I don't get the paint loop. This explains both the slow behavior, and the CPU utilization, but I am not sure at all why I am getting the multiple paintEvents.

Here's the code of my QDrawRect Object:



QDrawRect::QDrawRect()
{
setFlag(QDrawRect::ItemIsMovable);
setFlag(QDrawRect::ItemIsSelectable);
drawData.boundsRect = boundingRect();
drawData.shape = RECTSHAPE;
}


void QDrawRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QRectF joe = boundingRect();

painter->setRenderHint(QPainter::Antialiasing, itsWorksheet->wkAntiAliasing);
setBrush(QBrush(drawData.color));
QGraphicsRectItem::paint(painter, option, widget);
paintHandles(this, painter);
}

//
// JSL - updatePosAndBounds updates the position and bounds based on the drawData
//
void QDrawRect::updatePosAndBounds()
{
qreal x, y, w, h;

x = drawData.boundsRect.left();
y = drawData.boundsRect.top();
w = drawData.boundsRect.right() - drawData.boundsRect.left();
h = drawData.boundsRect.bottom() - drawData.boundsRect.top();
setRect(x, y, w, h);

setPos(drawData.pos.x(), drawData.pos.y());
}

stevel
30th April 2008, 00:32
Figured out what it was. In the code above, the setBrush call was causing an additional update. I'm not sure quite why. If someone that knows wants to enlighten me, I would appreciate it, but when I don't do this during the paint call, I don't get the paintEvent loop. (Which fixes my CPU utilization issue as well.)

pherthyl
30th April 2008, 03:50
You can use painter->setBrush() instead. There isn't much point in inheriting from QGraphicsRectItem. All it does is draw a rectangle, so you might as well do it yourself.

wysota
30th April 2008, 08:18
Changing any properties of the item while painting is a very bad idea. From what I see your item does the same the standard rect item does. Instead of discarding the QGraphicalRectItem inheritance as suggested, I'd suggest keeping the inheritance and using the class's methods to set its properties immediately when you know them (so in the constructor probably).

stevel
30th April 2008, 17:17
Thanks for the replies. I think this makes sense to me now. I will avoid modifying properties on a GraphicsItem during the paint procedure. I'm still not sure why modifying the paintEvent as in the fix above seemed to speed things up, however.

wysota
4th May 2008, 21:42
Because a different region of the viewport has been scheduled for update. It's too complicated to go into details here. You may download Andreas Hanssen's presentation about QGV from last year's DevDays when different update modes are explained. There are some tips how to speed things up there as well.