views:

992

answers:

1

I have a question about how to make marquee text smooth (using Qt 4.5.3) on not powerful hardware (Atom N270 + Intel 945GSM). My approach is as follows:

  1. I draw my text (36px Arial bold) onto a QPixmap (off-screen paint device)
  2. I set a timer to shift 1px content to left in each 30ms.
  3. When onTimer event is triggered, I make a selection of the QPixmap and print this part onto the window canvas.

Generally speaking, it moves smoothly. However, the more marquee text I create, the more CPU usage it reaches. When text can fill 50% screen (1920x1680), the CPU usage is about 70-80%. Text animation becomes a bit flickered. If I set timer interval to 50ms or larger, it will be smooth. But text moves too slow.

Is my approach ineffective? Shall I use OpenGL? Any hint is welcome and thanks in advance ^^)

+4  A: 

You should look into the Graphics View framework. You can add QGraphicsTextItem objects to a QGraphicsScene, and set the coordinates of the view (zoom and translation) to make your text move and appear whatever size you want, including having some of the text to be "off screen" (outside the view). I would expect this to be much more efficient than copying and painting a (varying size) portion of a QPixmap every timer event.

The documentation states that the Graphics View framework is optimized to handle many objects at once. If it turns out to not be any better, you might want to give the 4.6 beta a try. There are optimizations coming for the Graphics View rendering.

As an aside, I would look at QTimeLine for helping you to drive the animation. Besides providing basic "ticks" every so often, you can set "curve shapes" that can start out slow and speed up, or slow down as the end approaches. Just beware that if you want to restart your QTimeLine after the finished() signal, if you change the duration and call start() without calling setCurrentTime(0), the timer will start with the old duration as the current time.

Patrick
I tried QGraphicsSence before, but text looks aliasing. I don't know why. I will re-implement my code tomorrow and share the result.
stanleyxu2005
I too noticed aliasing when rendering QGraphicsPixmapItems, even when I did view.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform). But for QGraphicsPathItems, the aliasing is not noticeable. I would hope you would have better luck with a QGraphicsTextItem when you're using a larger font. When you tried QGraphicsScene, did you first render to a pixmap as you described in your question?
Patrick
Yes, I first render it to a Pixmap QGraphicsPixmapItems. But I think QGraphicsTextItem does not support marquee text effect.
stanleyxu2005
Okay, I understand the problem now. I would be curious if the performance is any better when using the Graphics View framework (even if you render to a QGraphicsPixmapItem). I plan to dig further into the aliasing problem, but it will take me some time to get there. I'll post back if I find anything.
Patrick
Thanks, if you can post some information here later. I think I should turn off double buffering using somewidget.setAttribute(Qt.WM_PaintOnScreen).
stanleyxu2005
It turns out you must call setTransformationMode(Qt::SmoothTransformation) on the QGraphicsPixmapItem in order for the smoothing to be applied. Calling setRenderHints on the view seems to have no effect (at least on X11), although the documentation for QGraphicsPixmapItem says the transformation quality depends on the viewport. In my opinion, the quality isn't that great. It would be nice to have better control over the types of anti-aliasing filters available.
Patrick
I found my issue. I use a timer to control the movement of marquee text. However, the timer will NOT be paused, while drawing is performed. Now, I stop the timer during drawing and resume it after that. It looks much better now.
stanleyxu2005