What I would like to achieve is similar to a board game. There is a 100*100 grid, placed inside an Item
which resides in a Flickable
.
The individual rectangles of the "gameboard" are svg images, currently there are around 20 types of them, this might increase into the low hundreds.
As a benchmark test, I just tried filling the "world" with elements:
Component.onCompleted:
{
var i,j;
for (i=0; i<100; ++i)
for (j=0; j<100; ++j)
{
var type = (i+j) % 20;
Qt.createQmlObject('import QtQuick 2.0; Image {source:"qrc:///icons/img/symbol'+type+'.svg";
width: 32*scaling.factor;
height: 32*scaling.factor;
x:'+i*32+'*scaling.factor;
y:'+j*32+'*scaling.factor}',
mainScreen);
}
}
This takes over 5 seconds on a moderately good PC.
However, after everything is loaded, it functions smoothly, both the scrolling and the zooming (scaling.factor
is a float set by a slider or spinbox).
The svg images are very simple, they contain only a few basic shapes. If I try just loading a simple rectangle instead of the svg image
Qt.createQmlObject('import QtQuick 2.0; Rectangle {color
: "red"; width: 32; height: 32; x:'+i*32+'; y:'+j*32+'}',
mainScreen);
It still takes around 3 seconds. Even though there are no images, and there is no dynamic scaling.
I remember that 20 years ago, there were strategy games running on computers with single core, less than 400 MHz CPUs, and those games had much larger maps, more complicated tiles, with animations, pathfinding, etc. And we are not even talking about 3d.
How can a modern PC choke on displaying a few thousand very basic shapes? It shouldn't be the loading time from disk, as the elements are in a resource file, and even the test with rectangles instead of images was horribly slow.
Not keeping all of them displayed, and only loading the elements near the border of the visible screen is obviously a way to go, or it would be if I had a 10000*10000 map. I would expect 100*100 items should be able to be displayed at the same time, especially as on a screen with a good resolution most of them would be visible.
Did I miss something obvious, or should I forget Qt Quick completely and should I do everything manually in OpenGL or some 2d engine?
Edit:
As suggested by the comments, Qt.createQmlObject
is very slow.
Therefore I tried
var component = Qt.createComponent("field.qml");
component.createObject(mainScreen, {"x": i*32, "y": j*32 });
Where field.qml
contains only a single Rectangle{}
, or, in a second test, just an empty Item{}
. In both cases the 10000 iterations took more than 3 seconds. Adding the svg to field.qml
only increased the time by 0.8 seconds.
By the way, aren't images supposed to be cached? Even if I have the same simple svg (which only contains 3 simple rectangles) repeated all over, it takes a lot of time.
Using a Repeater{}
makes everything considerably faster. Empty Rectangle
s are rendered in approximately 0.2 to 0.3 seconds, the svg images in one second. (This method has, however, other drawbacks. I'll post an answer when I finished testing different approaches)