PDA

View Full Version : Speed, transparency, and drop issues with QGraphicsView



jefferai
27th June 2007, 16:59
I've been running into speed issues with QGraphicsView attempting to do various operations. I was under the impression that all in-window drawing should be extremely fast, but that doesn't seem to be the case. What I want to do seems rather simple, but always ends up slow. I'm putting the genesis of my code below with appropriate questions sprinkled throughout.

Original idea:

I have a main window that currently has a QGraphicsView located in the middle. When a certain event happens, I want to have another QGraphicsView pop up with icons on it, semi-transparent over the original (so the original seems to "darken"). These icons animate as they pop up, by resizing.

So originally, I set the background:


setBackgroundRole( QPalette::Base );
QPalette p = palette();
p.setColor( QPalette::Base, QColor(0, 0, 0, 0) );
setPalette( p );
setAutoFillBackground( true );

And I then had a QTimeLine that would cause the alpha value to change. So when the timer fired:


QPalette p = palette();
p.setColor( QPalette::Base, QColor(0, 0, 0, value*4) );
setPalette( p );

But this was extremely slow. It also caused a "flash" when the QGV was shown or hidden (using show() or hide()) where the entire thing would flash white before drawing. So I tried simply setting it to a final transparency value from the beginning, without using the QTimeLine to change it. This was better but still very slow.

Question #1: Was I doing something wrong here? Can I expect to get decent partial-transparency speed somehow?

So at this point I decided to just use full transparency, which worked much more quickly. But still the "flash" persisted. Eventually I found out that I could start the "flash" on QGV's show by removing


setAutoFillBackground( true );

from the initial code segment above. Now, the items just seem to "pop up" on top of the QGV underneath. But when I hide() the QGV, it still does this "flash" and I've not found a way to get around it.

Question #2: What causes this "flash" and how can I stop it from happening on hide() (and on show() in case I want to have it fill the background)?

One thing I noticed at this point is that the QGraphicsView won't accept drops, despite


setAcceptDrops( true );

in my constructor. But the QGraphicsItems I add to my scene, which also have this set in their constructors, receive drops just fine.

Question #3: Why isn't the QGV accepting drops?

So at this point I have a transparent QGV with some items derived from QGraphicsSvgItem. They all share a QSvgRenderer so that I only have to read the SVG file once. At the moment, they are all the same item, so they all render the same graphic. I set up a QTimeLine to have these items resize so that they appear to grow in from nothing. But as my QGV gets larger, say, if my main window becomes bigger, this becomes extremely slow, and I'm not sure why (unless the answer is "because they're SVGs"). I want to use SVGs because I want the size of the item to change (and look decent) depending on the size of the QGV.

Question #4: Why is this resizing so slow, why is it affected by the QGV size, and can I do anything about it?

I think that's it for now. Thanks in advance.

guilugi
27th June 2007, 18:06
Did you enable caching for your graphics view ?
I know enabling it increases speed a lot !


graphicsview->setCacheMode( QGraphicsView::CacheBackground );

But this will work only if the widget that is below stays unchanged while the above one is visible..

markey
27th June 2007, 18:16
Did you enable caching for your graphics view ?
I know enabling it increases speed a lot !


graphicsview->setCacheMode( QGraphicsView::CacheBackground );

But this will work only if the widget that is below stays unchanged while the above one is visible..

Unfortunately this doesn't seem to be a viable solution. What happens is that the background is shown blank during the animation phase. Additionally I can't see any speed improvements :/

guilugi
27th June 2007, 18:17
Okay,

So can you provide me a code snippet that I can compile and test here ?
I can give then a feedback of the execution on my computer (I have a really powerful machine here at work :)

Guilugi.

PS : it could also be just a bug...check the Task Tracker !

jefferai
27th June 2007, 18:24
Not really...the code snippets in the first post are pretty much enough (just set the function that changes the transparency to a QTimeLine firing). I'm not interested in finding out if it appears fast on your really powerful machine, I'm interested in finding out why it's slow on normal machines.

guilugi
27th June 2007, 18:33
Well, it's always better to have exactly the same code as yours, to see if all the issues are exactly the same.

This kind of issues can be provoked by hardware, drivers...etc
And it can be quite different from a machine to another.

jefferai
27th June 2007, 18:37
You can find the latest version of the code here:

http://websvn.kde.org/trunk/extragear/multimedia/amarok/src/popupdropper/

You'd have to do a bit of tweaking around to actually have it run standalone...the code by itself should pretty much be entirely standalone but there's no main or qmake file.

Searching back in the history of popupdropperview.cpp you can see the various attempts at semi-transparent backgrounds of the QGV.

guilugi
27th June 2007, 18:41
Ok, thanks, that will help.

guilugi
29th June 2007, 15:17
Effectively, I have a lot of tweaking to make this sample work...you should have specified it was a part of amarok ;-)

I'll try to do this tonight.

jefferai
29th June 2007, 17:04
You an Amarok fan? Or just finding that to tweak you have to do a lot of building? :-)

The code's undergone some changes the past few days, so if you're trying things out, make sure you keep up to date with SVN trunk.

Thanks a lot for looking at this.

guilugi
29th June 2007, 18:38
Yep, Amarok is quite awesome ;-)

Maybe it would be faster to build the whole amarok source, instead of tweaking :)

Gopala Krishna
29th June 2007, 20:04
I've been running into speed issues with QGraphicsView attempting to do various operations. I was under the impression that all in-window drawing should be extremely fast, but that doesn't seem to be the case. What I want to do seems rather simple, but always ends up slow. I'm putting the genesis of my code below with appropriate questions sprinkled throughout.

Original idea:

I have a main window that currently has a QGraphicsView located in the middle. When a certain event happens, I want to have another QGraphicsView pop up with icons on it, semi-transparent over the original (so the original seems to "darken"). These icons animate as they pop up, by resizing.
[snip]
.

I don't get the proper idea(for now no time to look into amarok svn) so i may be wrong. I have completely different approach.

Firstly it'd be better to maintain just a single QGraphicsScene whereby you can control the updating of the whole scene in an effective way(updating items is obviously faster than whole scene).

Now to get the transparancy with single you can use a QGraphicsPixmapItem and set its Z value higher.

Again all the icons that were supposed to appear in different GV can be made to appear and animated on this scene itself. You can convieniently set their z values to maintain items at different levels.

Instead of hiding and showing the entire QGV you hide and show the items (pixmap and icons) which should result in enormous performance gain.

You might need to look into some of optimization flags like QGraphicsView::viewportUpdateMode(), QGraphicsView::OptimizationFlags and ofcourse QGraphicsScene::itemIndexMethod(). You can fine tune these flags to suit your case since the default might not be best for you.

About Drag & drop, I currently have no problems with my app. FYI i implement the scene's drag and drop methods(not view).
Probably this is your problem.


<offtopic>
Amarok is my fav music player and i'll be very happy with a windows port too(yup, even after the big flamewar in aaron's,..blogs) :cool:
</offtopic>

markey
30th June 2007, 09:50
I don't get the proper idea(for now no time to look into amarok svn) so i may be wrong. I have completely different approach.
[LIST]
Firstly it'd be better to maintain just a single QGraphicsScene whereby you can control the updating of the whole scene in an effective way(updating items is obviously faster than whole scene).

Now to get the transparancy with single you can use a QGraphicsPixmapItem and set its Z value higher.


I agree, and meh, basically I've been saying this all along. Why layer two separate QGV's over each other, when QGV already inherently supports Z-layering?

Time to "svn rm" the whole PopupDropper implementation and make a new start. A nice side effect should be a great reduction of code size.


PS: Thanks for the Amarok praise. Hopefully 2.0 will turn out to your liking :)

jefferai
30th June 2007, 15:45
Firstly it'd be better to maintain just a single QGraphicsScene whereby you can control the updating of the whole scene in an effective way(updating items is obviously faster than whole scene).

Part of the problem was that I was updating the items, but it was redrawing the entire view (even with the background a solid color). If I set QT_FLUSH_PAINT I could see that even though the boundingRect was sane on my items, as they scaled it'd redraw the entire thing.




Now to get the transparancy with single you can use a QGraphicsPixmapItem and set its Z value higher.

Which is actually harder, because it means we have to set the transparency of everything *else* higher, redraw those, and then draw these items on top with no transparency. I don't really see why this would be faster.

Also, you mention a QGraphicsPixmapItem, but I'd like to use a QGraphicsSvgItem, because I'd like for the items to scale depending on the size of the view. No point in having a huge view with tiny icons, just because they'll look crappy if they scale up. Is QGraphicsSvgItem really that slow to scale?




Instead of hiding and showing the entire QGV you hide and show the items (pixmap and icons) which should result in enormous performance gain.

Showing and hiding the QGV was never a problem, performance-wise. Scaling the items was. And since the other QGV had a solid background, I expect that doing it with a single QGV and having it blend different items with different Z-values while trying to scale others will result in an enormous performance decrease, not gain.

The "flashing" when doing the show and hide has nothing to do with performance...it doesn't matter if the QGV is tiny or large, it behaves the same. It has something to do with the implementation.




About Drag & drop, I currently have no problems with my app. FYI i implement the scene's drag and drop methods(not view).
Probably this is your problem.


This is non-obvious then. Why have view drag and drop methods if they don't do anything?

Gopala Krishna
30th June 2007, 16:54
Part of the problem was that I was updating the items, but it was redrawing the entire view (even with the background a solid color). If I set QT_FLUSH_PAINT I could see that even though the boundingRect was sane on my items, as they scaled it'd redraw the entire thing.

Well there should be some problem with your code since it never happens for me(i depend heavily on gv for ele-cad s/w). Have you verified this by printing a message in Item:: paint method ?



Which is actually harder, because it means we have to set the transparency of everything *else* higher, redraw those, and then draw these items on top with no transparency. I don't really see why this would be faster.

Its hard to imagine without a screenshots(i request you some). But what i meant was to use a transparent pixmap(or svg) that covers the view. This pixmap stays in an intermediate layer and the icons are animated in topmost layer. So why should you set transparency for everything ?



Also, you mention a QGraphicsPixmapItem, but I'd like to use a QGraphicsSvgItem, because I'd like for the items to scale depending on the size of the view. No point in having a huge view with tiny icons, just because they'll look crappy if they scale up. Is QGraphicsSvgItem really that slow to scale?

Matrix transformations generally slow up things but gv should be able to handle this(chip demo). I leave this question for someone else to answer since i've less experience with svg.



Showing and hiding the QGV was never a problem, performance-wise. Scaling the items was. And since the other QGV had a solid background, I expect that doing it with a single QGV and having it blend different items with different Z-values while trying to scale others will result in an enormous performance decrease, not gain.

The "flashing" when doing the show and hide has nothing to do with performance...it doesn't matter if the QGV is tiny or large, it behaves the same. It has something to do with the implementation.

Have you tested both the ideas ? It usually won't decrease performance. The chip demo for example works pretty well at different scales(not extremes though). Though this demo doesn't demonstrate layering it proves its management capabilities for large number of items as well as scaling them. You can use QGraphicsItem::ItemIgnoresTransformation flag to avoid scaling the icon items.
IMHO its better to blend items into a single scene(still i feel same)
And for flashing, i don't have a clue.
BTW, i still dont get the "basic idea" about what you are trying to achieve ? Screenshots will surely help me realize your idea.

Gopala Krishna
30th June 2007, 16:57
This is non-obvious then. Why have view drag and drop methods if they don't do anything?
Because you can have multiple views for a single scene. So the result of drag and drop done on one view should be reflected in anothers. Hence it provides us "convienient" way to do things. :)

fullmetalcoder
30th June 2007, 17:14
This is non-obvious then. Why have view drag and drop methods if they don't do anything?
They actually do something : they call the method of the scene... :p And as already pointed out they ensure D'n'D does not mess up shared scenes...