PDA

View Full Version : How do I find out which widgets/canvas items are visible?



Tommytrojan
5th January 2006, 18:17
Hi,

I need to find out which parts of which widgets are actually being shown. Usually the system will post a paint event when a widget needs to be redrawn, however, I have changing data which I want to display dynamically. The computation of the data is expensive and if the widget (canvasview) is obscured but other windows. The isVisible property is not sufficient since it is true even if the view is obscured. Ideally I would like to know which canvas items are visible and even parts that are visible. I don't know if I can reuse the paint engine for this since that must figure out which parts need to be redrawn. It seems like the draw() method is called every time I call an upate() on the canvasitem regardless if the item is actually visible or not. I know that the paint engine knows if an item is visible or not since no draw() method is called when the item is obscured and I move a window over it.
I would like to avoid the costly preparation of my data if it can't be seen anyway.

Any ideas how to handle this?

Thanks,
Tom

wysota
5th January 2006, 18:28
In the paint event you have all the information you need.



const QRect & QPaintEvent::rect () const
Returns the rectangle that should be updated.
See also region() and QPainter::setClipRect().
Examples: life/life.cpp, qfd/fontdisplayer.cpp, showimg/showimg.cpp, t10/cannon.cpp, t11/cannon.cpp, t13/cannon.cpp, and tooltip/tooltip.cpp.

const QRegion & QPaintEvent::region () const
Returns the region that should be updated.
See also rect() and QPainter::setClipRegion().
Examples: qfd/fontdisplayer.cpp and scribble/scribble.cpp.

jacek
5th January 2006, 18:31
Any ideas how to handle this?
Maybe you could deduce whether the item is visible from the region returned by QPainter::clipRegion()? Although it might not work for every update.

Tommytrojan
5th January 2006, 19:29
Thanks for the quick answers.

The problem is that the update() call on the canvas item causes the canvas to repaint all views that have that item set to visible. So as long as I call update() the paint even will include all these items to be updated, which is perfectly fine. However, I call update() on any data event my system delivers (think of it as a stock ticker). Now, if the canvas item is obscured it still gets the paint event (actually a draw() for the canvasitem). So I guess what I need is a function that tells me if a particular canvas item is obscured and therefore I don't even need to call update(). I can do this in a limited fashion for windows that are iconized since I know that the canvas view won't be able to show these items but if the user keeps all the windows open (and they could have hundreds of windows) I have no idea which ones are actually visible.
How does Qt know which widgets and canvas items to repaint? It must have a notion of 'visible' widgets/items.


Thanks,
Tom

axeljaeger
5th January 2006, 19:37
You can check wether an item's bounding rect:

http://doc.trolltech.com/4.1/q3canvasitem.html#boundingRect

intersectsWith:

http://doc.trolltech.com/4.1/qrect.html#intersects

the rectangle to draw:

http://doc.trolltech.com/4.1/qpaintevent.html#rect

jacek
5th January 2006, 19:38
However, I call update() on any data event my system delivers (think of it as a stock ticker).
Which update() do you call?

Tommytrojan
5th January 2006, 20:14
Axel,

that doesn't solve the problem. I need to know 'before' I call the update() of my canvasitem if the item would be in the paint region, once I get the paint() event it is too late since I have to provide the data by then.

I have to call update() once my system has new data available, however, I DON'T want to call update() if the item is obscured and won't be seen. Once I call update() the entire item (QCanvasItem) will be in the paint region anyway, so the decision to call update has to be made prior to the paint event (which hopefully never happens if the item is obscured to begin with). I hope I stated the problem correctly.

Thanks,
Tom

Tommytrojan
5th January 2006, 20:21
Which update() do you call?

Jacek,

I call QCanvasItem.update(). Well, it is a subclass where I implement the drawing of the item. Whenever a data even occurs in my system I have to go through a lengthy formatting procedure and prepare the output, then I call update() to get the data rendered. I would like to not have to go through the formatting if the item is not being displayed anyway. So what I want is:



fOnData(char* szData)
{
if !isObscured()
{
fFormatData(szData);
update();
}

// Ignore data as it is not rendered anyway
else
{
}
}

If the items gets uncovered and a paint even issued I can recover the data and do the formatting then. The data events occur with a 100ms frequency and there can be thousands of them, so it is important to not incur this overhead until it is really needed.

Thanks,
Tom

wysota
5th January 2006, 20:50
Maybe QCanvas::setChanged() helps you? If you look at its source code, you'll notice how the canvas stores its changed regions. While an update() is issued, it checks which regions of the canvas need updating and updates only those parts of the sheet.

jacek
5th January 2006, 21:00
I call QCanvasItem.update(). Well, it is a subclass where I implement the drawing of the item. Whenever a data even occurs in my system I have to go through a lengthy formatting procedure and prepare the output, then I call update() to get the data rendered.
QCanvasItem::update() only marks canvas chunks as modified. IMO it shouldn't trigger any repainting (the docs say something different, so I might have missed something when I was reading the sources).

BTW. You can try tuning the QCanvas chunk size. Also make sure that your item reports proper bounding rectangle.

Tommytrojan
5th January 2006, 22:26
QCanvasItem::update() only marks canvas chunks as modified. IMO it shouldn't trigger any repainting (the docs say something different, so I might have missed something when I was reading the sources).

BTW. You can try tuning the QCanvas chunk size. Also make sure that your item reports proper bounding rectangle.

Well, the item gets updated properly, so I assume that the bounding rectangle and everything else is okay. The problem is that it does get updated every time! I would like it to invoke my draw() function only when it actually is visible. However, I calls my draw() function even when it is obscured...

T

jacek
6th January 2006, 14:22
Well, the item gets updated properly, so I assume that the bounding rectangle and everything else is okay.
Yes, but the bigger bounding rectangle is, the more likely update is to occur.


The problem is that it does get updated every time! [...]However, I calls my draw() function even when it is obscured...
It looks like Qt doesn't know that a part of a window is hidden under another one.

In case somebody wants to research this subject further, I've attached a little program I wrote to test few ideas.