简体   繁体   中英

Display text inside QGraphicsPolygonItem without copying std::string to QString?

I am using QGraphicsScene to draw millions of polygons. I plan to use Qt+OpenGL later, but for now I am not drawing more than 1 million polygons and Qt handles it just fine. The problem arises when I try to display text inside the polygons.

Each polygon (a custom class inheriting QGraphicsPolygonItem) is a visual representation of an object, and has pointer to that object associated with it. Each object has a std::string identifier. If I could simply display that string inside the polygons, it should be fine memory-wise. However, Qt seems to need a QString instead, and it takes a lot of time and space to convert every string. I am creating a QGraphicsTextObject for each polygon and each of those needs a QString copy of the std::string . Is there any way to bypass this copy using just Qt?

Cropping the scene is not desirable. There are some polygons that are too small for any text to fit inside them, and one can only see them by zooming in the scene. These polygons (and their text) need not be displayed (unless the user zooms in), but I don't think that would help without creating various other issues first.

PS: Displaying the text on-demand (as the user hovers the mouse over each polygon, for instance) is possible, however it'd be ideal if the text was readily displayed.

Have you profiled it to see if the conversion is actually your bottleneck? Font rendering isn't exactly fast, and if actually tries to render millions of texts, that will be slow. You won't get around the string conversions, the only thing I could think of is to optimize when to do them, and how often.

First, I'd consider to use a custom item either painting the text manually by reimplementing QGraphicsItem::paint, or deriving from eg QGraphicsSimpleTextItem , which allows more tweaking than using QGraphicsSimpleTextItem or even QGraphicsTextItem directly, both which require you to call setText() and thus convert the string upfront.

One thing to be conscious about is when the conversion would be done. With a custom item, you wouldn't need to do the std::string to QString conversion upfront (when calling setText()), but you could store the std::string and do it on demand only, in your paint() implementation, ie convert on first paint() call and then cache.

Another potentially expensive calculation is boundingRect(). This could be tweaked by returning a less precise approximation of the actual text shape. It doesn't hurt if the returned rectangle is somewhat bigger than the actually painted rectangle, it just shouldn't be smaller. So one could use a hardcoded height * approx. letter width + some padding.

Then, text not drawn at all is even cheaper. If the view is so zoomed out, that 10^6 items are drawn (and only then paint() is called), one will have a hard time to read any text. I'd reimplement paint() and make use of QGraphicsView's level-of-detail mechanism (see here ) and just not convert the string nor paint anything below a certain level of detail/zoom level.

If you can use Qt 5.4, QGraphicsScene::minimumRenderSize might also come handy. But that alone won't avoid the string conversions nor the boundingRect() when not combined with the other suggestions above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM