January 12, 2011

pjoe pjoe
Lab Rat
15 posts

Showing animated progress while loading large QML files

Page  
1

Hi,

I asked this on the mailing list, but thought I might as well also post it here :)

I’m working on a QML based app. where I dynamically load ‘sub’ applications or plugins at runtime. However when running on maemo, loading of all the QML files of such a sub-app. takes quite a long time (5-10 secs, enough for the end user to be annoyed), so I’m wondering if there is a way to at least show an animated loading screen while this is going on. I’ve tried a couple of things, but haven’t really found a satisfying solution:

  • Wrap the QML in a Loader: This allows me to show a static loading screen, but as soon as I ask the loader to load the rest of the QML content, all animation is blocked while it’s loading.
  • Load the QML in a background thread: This fails because the QML contains a lot of images which in turn creates QPixmaps, which doesn’t work from another thread than the main ui thread :(

I’ve done a number of things to speed up the actual loading itself, but I don’t think I can get it much faster:

  • Prefetch the QML, i.e. have the QML engine load the same QML file so it caches the parsed version of the QML
  • Prefetch images, i.e. have the image loaded into QPixmapCache ahead of time

Any help appreciated,

-pjoe

18 replies

January 13, 2011

pjoe pjoe
Lab Rat
15 posts

So far my best bet is to draw progress indication from a separate thread using opengl. I found this article on multithreaded opengl in Qt: http://doc.trolltech.com/qq/qq06-glimpsing.html#writingmultithreadedglapplications

January 13, 2011

Andre Andre
Robot Herder
6295 posts

I am really wondering what’s blocking the animations (GUI thread?) while loading. I am starting to think that this is a bug. Access to resources should be asynchronous, right?

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

January 13, 2011

krishkn krishkn
Lab Rat
32 posts

There is WorkerScript{} element which runs in a sperate thread other than main GUI thread.Just try to use tht,might help :)

 Signature 

Regards,
Krishkn

January 13, 2011

Mohsen Mohsen
Lab Rat
748 posts

try this http://doc.qt.nokia.com/4.7/qprogressdialog.html

 Signature 

www.madagon.com

January 13, 2011

pjoe pjoe
Lab Rat
15 posts

Thanks, I did try worker script .. it doesn’t help :( The issue is that when loading the main QML content the whole ui thread is blocked, so it’s not possible to do any screen updates. And because QML Image items use QPixmaps, the actual instantiation of the QML hierarchy can only be done in the ui thread.

I should also note that the QML content is loaded from resource files, so it’s not getting the data that’s taking time, it’s building the QML hieararchy (and to some extent creating pixmaps as part of that).

I’ll have a look at QProgressDialog, but it looks like it is also supposed to run in the main ui thread. If that’s the case it again doesn’t help here :(

January 13, 2011

2beers 2beers
Lab Rat
149 posts

I have to say I come to the same problem. And WorkerScript doesn’t help. Maybe it’s a bug. you should fill a request at http://bugreports.qt.nokia.com

January 13, 2011

Kxyu Kxyu
Lab Rat
145 posts

well, I guess we need to see your code

January 13, 2011

pjoe pjoe
Lab Rat
15 posts

Here is the source I’m using for loading QML (I’ve removed some error handling and debug output for readablility). The time is spent in beginCreate() and completeCreate(), which creates the QML hierarchy and blocks the ui thread.

  1. void MyDeclarativeView::setSource(const QUrl& a_Url)
  2. {
  3.     m_Url = a_Url;
  4.     if(m_Root)
  5.     {
  6.         delete m_Root;
  7.         m_Root = 0;
  8.     }
  9.     if(m_Component)
  10.     {
  11.         delete m_Component;
  12.         m_Component = 0;
  13.     }
  14.     if(!m_Url.isEmpty())
  15.     {
  16.         m_Component = new QDeclarativeComponent(engine(), m_Url, this);
  17.  
  18.         QObject *obj = m_Component->beginCreate(rootContext());
  19.  
  20.         m_Component->completeCreate();
  21.  
  22.         if (QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem *>(obj))
  23.         {
  24.             m_Scene->addItem(declarativeItem);
  25.             m_Root = declarativeItem;
  26.         }
  27.  
  28.         if(m_Root)
  29.         {
  30.             QSize initial = rootObjectSize();
  31.             resize(initial);
  32.             scene()->setSceneRect(0, 0, initial.width(), initial.height());
  33.         }
  34.     }
  35. }

January 14, 2011

Mohsen Mohsen
Lab Rat
748 posts

have you tried QThread too? to implement you own “please wait” dialog?

 Signature 

www.madagon.com

January 14, 2011

pjoe pjoe
Lab Rat
15 posts

I’ve tried loading the QML in a background thread, however this fails because while creating Image items QML will create QPixmaps, which can only be done in the main ui thread :(

So what I thought was to make the progress indication in another thread, but this requires that this thread is able to actually update the display and the only solution I’ve found for that is using opengl, unless somebody know of a way to refresh the display from another thread without opengl.

January 14, 2011

Mohsen Mohsen
Lab Rat
748 posts

is your process running on a loop like “for” or “while”? then you should use QApplication::processEvents(); inside your loop.

 Signature 

www.madagon.com

January 14, 2011

Mohsen Mohsen
Lab Rat
748 posts

for making connection between threads you can use Signal and Slots but i prefer to implement a class inherited by QThread

 Signature 

www.madagon.com

January 14, 2011

Andre Andre
Robot Herder
6295 posts

mohsen, that is of little use if the GUI thread is already blocked by a Qt function, as explained above.

pjoe, I think your openGL may be the only way to circumvent this limitation at the moment, other than hacking in the Qt code itself to see what the holdup is. The only other thing that pops into mind is to see if the scenegraph QML backend is mature enough for your needs. At the DevDays session [qt.nokia.com], it was still very much a research project, but it was on the roadmap shown by the Qt CTO (much to the suprise of the author of the research project, by the way).

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

January 14, 2011

pjoe pjoe
Lab Rat
15 posts

As Andre noted, the whole ui thread is blocked during beginCreate and completeCreate, so queued signals or events won’t arrive until the QML loading is completed.

I’ve read about qml-scenegraph, and I think it is definitely the long term solution, but as I understood it is currently based on a branch before 4.7.0, so probably not quite ready for production use … yet.

Unfortunately I’m also facing the problem that opengl is currently broken on the final target system – I’m just using maemo for testing, the end product is running on a custom embedded linux device (also arm based, with opengl hw).

January 14, 2011

Andre Andre
Robot Herder
6295 posts

very hackishm & ugly workaround: spawn another process to display an animated overlay?
Sound like a waste of resources, but if you really need it, it may be the escape you need.

Sorry that scenegraph is not far enough for you yet, that does not really suprise me, but it was worth suggesting. There was an interesting demo in the session showing an 8-thread simultaneous rendering of a single QML scene. That was the first time I ever saw multi-threaded UI rendering using a single process…

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

Page  
1

  ‹‹ [Moved] QML vs Qt      QDeclarativeStyledText in my custom QML QDeclarativeItem ››

You must log in to post a reply. Not a member yet? Register here!