Warm tip: This article is reproduced from stackoverflow.com, please click
c++ qml QT qtquick2 qquickitem

To paint some small tiles on the screen, should I use QQuickItem or QQuickPaintedItem?

发布于 2020-04-08 09:33:09

Essentially I need to load up a 4-color tilemap in memory that's exactly 16K in size, animate 2 of the tiles maybe 3 times a second, and render out a few tiles into a fairly small box, I'd say maybe 100 or so pixels wide and maybe 80 pixels tall (very roughly from memory) to be shown in QML/Qt Quick which I might use the scale property to scale it up larger in QML

Anyways I'm kind of at a loss on how to do this but I'm going to presume C++ is the best bet for this which is fine by me and after researching around I see there's 2 main options, QQuickItem & QQuickPaintedItem.

Now I understand QQuickPaintedItem is older and slower because it draws in the CPU first and then copies out to the video card so it's not the best solution. The most recommended option is QQuickItem which renders on the Graphics Card with OpenGL.

But I don't need something that's overkill, I mean I'm dealing with ~100 x 80 pixels here, There's no line or shape operations, there's no shaders, none of that. It's just a bunch of pixels so I'm wondering if it'd be better to just use QQuickPaintedItem.

However there may be another solution to all of this I don't know of in which case I'd love to hear it, maybe there's a much easier way to all of this.

Any help to figuring this out would be great, thanks in advance.

Questioner
June
Viewed
89
June 2020-02-01 11:41

As usual I'm looking for the simplest solution that fits my needs and I found it.

I created a TilesetEngine class that loads the tiles in QImages (because it's so simple), processes them, and then converts them over to QPixmaps where they're broken up into individual tiles and cached in memory for speed (perks of tiny simple 8x8 tiles, there's no memory footprint). The engine allows you to directly request a frame number and it'll render the static image with animated tiles matching the requested frame number.

That was the hard part because there was quite a bit of processing and post-processing but with that out of the way I created a QQuickImageProvider that serves as a sort of loose bridge and allows for a for extra options in the "id" such as specifying a scale size in the id since Qt Quick wasn't calling the const QSize& requestedSize. This was pretty easy to do.

With that registered to QML I just drop in a single id string, the id string specifies all options of how I want the engine to render the tileset from the animation frame, certain overlays, which tileset, etc... and the id string also tells the provider if I want it scaled or if I want the whole tileset image or just a single tile id. This was also super easy a lot of fun.

Then for more fun I threw in a timer in QML and requested all the frames in the animation one-by-one and had it loop around. Here I could watch the animation and tileset or tiles come to life and animate.

The whole thing was very straightforward, easy, and a ton of fun. The only hard part was the engine whcih got real gritty in pixel manipulation but QImage, QPaint, QPixelmap, and QColor took th bulk of the work out so it could have been more difficult if it weren't for Qt's convenience classes.

I'm so glad I never mangled with any of the OpenGL stuff or my original plan, a QQuickItem or QQuickPainted Item. This solution was perfect and easy and fits everything I need it to do,