Using QtQuick Loader vs the property visible - qt

Let's say I have a general implementation to represent a screen. The screen has a footer. The footer can have the following content:
empty or
one button on the left or
one button on the right or
one button on the left and one button on the right
I have at least 20 instances of this screen implementation within my application. I was wondering if it is better to load the buttons with a QML Loader component only if they are used within the given screen or it doesn't make that big of a difference to have the buttons always there just turn on/off their visibility?
Sidenote: each screen knows upfront how many buttons will it need if any.

It wouldn't make a lot of difference in most cases. The trade-back is CPU time vs RAM usage, hiding will save CPU time but use more memory, creating and destroying will save memory but add CPU load.
It would only begin to matter if the components are heavy and complex, which means that they will be slow to create, and use a lot of memory, in that case you have to decide based on which of the two you prefer to avoid.
Unless you already have established to have a problem with how your app performs, don't bother with premature optimizations.

Related

Dynamically changing component arrangment in QML

What would be the preferred (recommended) way to rearrange the components of a QML UI on an event such as a button click?
I do have designed a UI consisting of a bunch of custom components, each of them is bound to a (C++) model. I use anchors to position the components in the ApplicationWindow.
On a button click, I want to add an additional component which, due to its size, makes it necessary to rearrange the existing components. Actually, the button could be understood as switching into a different mode such as the Debug view in an IDE (think of Eclipse).
My goal is to keep the components in a consistent state between views and make the switch as fluent as possible.
I could think of these options:
Design two different views, and use a Loader or State to switch between them. As initializing the models takes some time, they should remain not be deleted during switching. I think, setting them as ContextProperty of the QMLApplicationEngine should take care of that.
Do a lot of rearranging in the onClicked()-Handler of the button. Probably the worst solution but does not require to reinitialize the components and models.
I think the most elegant solution would be to initialize the components in a some kind of container (or model) and then assign different layouts to this container on button click. But I have no idea, if this is possible and how to achieve that.
Edit: I followed approach 1. by using the StackLayout. It works basically, but it seems as if the invisible UI is still running in the background and consuming resources (e.g. requesting Images from my QQuickImageProvider).
Using a Loader eliminates this problem as it destroys the previous UI on every change of the source property. What I do like about the StackLayout however is that it preloads all UIs on app startup. So the transitions are smoother compared to the Loader. Is there a way to disable the invisible UIs?
Your option (1) is the one giving your the most flexibility, since you have two entirely separate UIs depending on state.
As you already discovered yourself this requires keeping all relevant state data in a way that is accessible by both UIs, e.g. in C++ or in globally accessible QML/Script objects.
I would go for that if you envision any more changes or tweaks than just rearranging elements.
If you are sure that rearranging elements will be sufficient, have a look at QML states
It is a bit like a combination of your options (2) and (3).
The state setup allows you very locally to define anchors and other properties for each element depending on a named state.
The button's signal handler then only needs to change which of the states is active, by assigning one of the names to the respective state property.

Qt custom widget update big overhead

We are trying to use Qt 4.8.5 for some Linux-based embedded devices in our company. I use Qt embedded without X server. I need to plot measured data and update them very often (20-30fps, but only a small portion of the widget). The system is ARM based, 400Mhz, have no GPU and no FPU. I subclassed QWidget and overridden the paintEvent(). I have WA_OpaquePaintEvent and WA_StaticContents set. For testing, my paint event is empty, and I call the update() function of the widget form a timer set to 50ms. My problem is that the empty update is eating up 30% of the CPU. The amount varies with the area of the update, so I think QT may redraw something in the background. I have read many posts but I cannot find the solution for my problem. If I comment out the update call, the CPU usage drops to ~1% (even if I generate a sine in the timer for testing the widget, which should be much more complex than an empty function call). My widget is rectangular, is not transparent and I want to handle the full drawing procedure from the paint event.
Is it possible to reduce this overhead, and handle the whole painting process by my own?
The "empty update" is not empty - it repaints the whole window :)
Have you read the below?
To rapidly update custom widgets with simple background colors, such as real-time plotting or graphing widgets, it is better to define a suitable background color (using setBackgroundRole() with the QPalette::Window role), set the autoFillBackground property, and only implement the necessary drawing functionality in the widget's paintEvent().
You should also be using QWidget::scroll(), since internally it does scroll the backing store of the window, and that's much more efficient than repainting the entire thing if only a tiny slice is added to it.

Flex tabbed view gets reloaded every time

I have a very simple Flex application for mobile phones which uses 3 tabs (with the TabbedViewNavigatorApplication).
It seems that everytime I switch tabs, the selected view is reloaded.
I've set a creationComplete command to do something and everytime I click on the tab it executes the function.
Isn't it possible for the views to get loaded 1 time and that's it?
Seems to me that this behaviour is exactly the point on mobile devices since you want to keep memory / cpu usage as low as possible.
This effectively means destroying all non-active views and all related view components / objects.
However you can override this default behaviour by setting the destructionPolicy on every view to destructionPolicy="never".
This blog post will explain the basic understanding you will need to obtain.
Cheers

Flex app with large number of UI objects == slow?

I'm building my first Flex custom component, in Flex 3. It is a data table based on the 'Grid' container class, with a simple text Label in each cell. (DataGrid and AdvancedDataGrid were not appropriate starting points for my needs.) The component works quite well using smallish tables, but I tried stress-testing it using a larger table, and have been disappointed by the results.
The component creation process has some slow spots, but those are in my power to optimize and aren't my primary concern. What worry me more are what appear to be limitations in the Flex framework itself.
This 'large' sample table has a bit over 7000 cells in it. This is largish, but still 1-2 orders of magnitude less than the biggest I need to accommodate. In standard Grid structure, the main portion of the component consists of a Grid with 400 GridRows of 16 GridItems each, plus a few other smaller ancillary Grids.
Once the table renders, I find the following:
Mouse-related events are slow to fire. Specifically, I have rollOver/rollOut event handlers registered on each table cell, to let me highlight the cell under the pointer. On a small table, I could move the mouse over the table very quickly, and the highlighting would follow the pointer in real-time. With the larger table, the highlighting is very jerky, changing only about twice per second, skipping over many cells.
If I place the mouse cursor over the component and leave it there, my CPU is pegged (one processor core, anyway), and stays that way until I move off of the component, when it drops to idle. My component isn't doing anything at all at this point.
It feels like Flex simply cannot scale to support component trees that are this large. I shudder to imagine how it would behave with 100,000 cells. Perhaps I'm pushing the Grid beyond its intended use, but having an object per table cell doesn't seem like an unreasonable model, and ~14,000 objects in the tree (a GridItem and a Label per cell) seems pretty modest.
I have yet to get useful data out of the FlexBuilder profiler; I'm working on it. For now, my biggest questions are:
Am I really pushing the limits of Flex with this modest test?
Is my approach to this component completely off-base?
I'm running this on Flash Player 9 under Firefox on WinXP.
Yes, Flex is not designed to support very large numbers of components, it is well known that you should minimize the number of components and don't use features that you don't need (Eg. DisplayObject instead of Canvas if you don't need the extra functions).
It's unwise to mirror your data exactly with displayed objects. DisplayObjects (and related classes) are relatively heavyweight, and you need to control how many of those you have.
I would say that the scale you're working at, with 1000+ Cells, and an event listener for each one, would definitely reach Flex's limits.
I think you should take a better look at your approach and architecture. I assume you are not displaying all 1000+ items at the same time, perhaps you should use paging and display 100ish with each screen, with previous/next buttons to move on to another page. You could also consider dynamically adding and removing rows using a custom scrollbar, simulating the scroll effect. This is much more complicated to do.
Boy, it seems we can write a book on this topic. Or atleast a chapter. We learnt quite a few things in this area as we were developing our products.
Bottom line - yes, Flex will slow down to a halt when you add 1000+ "things" on the screen. Here are a few bullet points, and some repetitions of what's already mentioned (just to be concise)
1) Always draw only what is visible. Hans Muller, the architect on the new Spark DataGrid has a great writeup on ViewPorts. http://hansmuller-flex.blogspot.com/2009/06/introduction-to-viewports-and-scrolling.html. So instantiate enough "cells" to fill up the visible area, and basically recycle them as the user scrolls.
2) Recycle, recycle, recycle: Further to above, as the user scrolls, you obviously have to recycle cells that are now out of view to show the ones that are in view. Here there are a few things we learned the hard way :-)
-> Instead of disposing and creating new cells, either use reparenting or use repositioning (prefer repositioning)
What this means is this: Say you have a 10X10 grid (visible) showing a 100X100 data provider.When the user scrolls to cells 20X20, the quickest way will be to set the X and Y of the existing cells to the new locations, and then call set data for each. We used reparenting earlier because our scenario was a series of related containers, so this may not apply to you. But bottom line - we simply move "rows" around the visible area. So creating and destroying will be slow, removing and adding to the display object list will be faster, and just moving around (x,y) will be fastest.
3) Choose what you inherit from wisely: The Flex SDK is a beast. So choose your "cells" base class wisely. For example, the SDK DataGrids, have a lightweight renderer that inherits from UITextField (Halo), as opposed to Label. Even UIComponent will be heavy in certain scenarios. Look up the asdocs for UIComponent and see if you need everything in there, else consider inheriting from further up its hierarchy.
4) Cache Calculations: Do this last in your development cycle. Once you are done with a feature, run flex profiler. Identify the longest running methods, and the most called methods. We always do this when we release, because there's always improvements to be made. There's a lot of math involved when you're developing a highly visual component, and too many calculations will slow things down.
5) Make sure you profile for memory : Unwired event listeners, rogue object references, etc will kill performance. Flex profiler is an excellent tool to combat this, so make sure you use it.
We have some good links here:
http://www.flexicious.com/resources/Ultimate/Docs/LargeDataset.htm?
Hope this helps!
If you look at any List-based control in the Flex framework, you'll see that they make significant use of item renderers which are recycled. So a DataGrid with 20 rows displayed only creates about 22 renderers and recycles them as you scroll through the list. This is why a DataGrid can hold thousands of records and still have pretty snappy performance. I recommend you check out Peter Ent's series of articles on item renderers and take a look at ListBase/List and some of the related classes to understand how to build something similar:
http://weblogs.macromedia.com/pent/archives/2008/03/itemrenderers_p.html
Without seeing your code and knowing exactly what you're trying to do...it definitely seems like you're pushing the limits of Flex by pushing that much data into the framework all at once.
Keep in mind that the Flash runtime wasn't designed to handle huge applications...but run somewhat light applications inside the browser. It also seems unlikely that your users are going to need to have access to all of those controls all at once.
You could try providing data services (Java, .NET, etc.) to drive the data in your application. You would then page through the data so that the framework is only dealing with maybe 200 - 300+ elements at a time.
In flex, if you using Mouse move event to redraw anything .. You might have experienced very slow rendering .
eg:
this.addEventListener(MouseEvent.MOUSE_MOVE, redraw);
and
public function redraw(anything:Object=null):void{
//draw something here
this.graphics.clear();
this.graphics.lineStyle(3, 0x000000);
this.graphics.moveTo(startPoint.x, startPoint.y);
this.graphics.lineTo(endPoint.x, endPoint.y);
this.scaleTextInput.x = centerPoint.x;
this.scaleTextInput.y = centerPoint.y;
}
The Above code results very slow rendering ...
Solution:
Use Event.ENTER_FRAME event instead? Although more resource intensive than the mouse move event, you should receive considerably more updates per second, allowing the mouse to appear more responsive to the user:
Eg:
this.addEventListener(Event.ENTER_FRAME, redraw); instead of
this.addEventListener(MouseEvent.MOUSE_MOVE, redraw);
and You are good to go ..Happy Flexing
More on:
http://www.deepakdhakal.com

Flex Post Event Screen Updates

I came across this topic today while investigating something very strange. Doing certain things in our Flex app can cause the number of frames rendered to rocket, from 12fps to ~30fps: loaded animations start playing at high speed and the GUI starts to lock up.
Since everything I've read on Flex/Flash hammers home the point "the frame rate is capped at the fps set in the top level app", it seems the only way these extra renders can be happening is due to some events causing them (no programmatic changes to the stage's framerate are done anywhere). Since it only happens when I put my update logic in the ENTER_FRAME handler, I'm trying to figure out what might be happening which to apparently causing Flex to go render-crazy.
Hypothesis: something in my update function is triggering an immediate screen update, this raises another ENTER_FRAME immediately, which means my update loop gets called, which triggers another immediate screen update, ...
We have Flex components used in our GUI, if this is a factor. I don't really know where to go next on this.
Clarifications:
When I say things speed up, there
are two ways this manifests.
Firstly, my ENTER_FRAME handler gets
called far more often.
Secondly, a
loaded Flash SWF with a looping
animation built in suddenly speeds
up to te point it looks silly.
I am not using updateAfterEvent, I only
found this existed when researching
this problem. Apparently, some
events on Sprite subclasses
automatically call this and I wonder
if that's the root cause.
I am not doing any direct messsing about with rendering at all. Background animations play automatically as they have timelines built-in from CS3 authoring, all our update function does is change the position of DisPlayObjects or add/remove them etc
Update:
I added a label to my app to print out stage.frameRate, and discovered at certain times, it suddenly changes from 12 to 1000 (the maximum allowed value). While it was trivial to add a line to my ENTER_FRAME handler to reset it that's hardly a big help.
Also, even doing this, the rendering is all messed up. Certain actions (like raising an Alert popup) make it all spring back into life.
Unfortunately, I am not able to view the source of the Stage class to set a breakpoint on the setter property.
That's very interesting about the Flex loading 'set to 1000fps' thing. What we have are several Flex applications which all provide a common interface. A master app is in charge of loading these modules as required through the SWFLoader class. However, the loading process already takes into account the delayed loading... when the SWF loads we then wait for the APPLICATION_COMPLETE from the SystemManager. Once this is received, shouldn't the applications completion have occurred?
Flex sets the frame rate to 1000 during "phased instantiation" of Flex components, which occurs only during initial load of a flex swf. This allows it to build all components very quickly.
Are you waiting for the Flex app to be fully loaded and constructed? You should be waiting for FlexEvent.CREATION_COMPLETE before working with your Flex content.
If you would like a reference to where this occcurs, look in the Flex LayoutManager class, line 326 (using Flex SDK 3.0.194161), in the setter for the property usePhasedInstantiation.
Update:
APPLICATION_COMPLETE should have you covered for the initial load.
This actually happens any time components are created directly from MXML. So there are a few other cases to look for. Are you using any Repeaters? Do you use any navigation containers that are building their children on demand?
One thing I'm not clear on - are you seeing that the actual screen refreshes are occurring faster than the published framerate? Or is it that your animations are moving faster but the screen refreshes are unchanged? (i.e., it used to move 10 pixels per second, but now it moves faster than that, regardless of how often the screen is drawn.)
An easy way to check this would be to try publishing your content at 1 fps. It should be clear whether the screen is redrawing once per second, but animated elements are being moved more frequently than that, or whether the screen is actually updating more frequently.
If the latter, are you using any updateAfterEvent() methods in your code? This can cause actual screen refreshes to occur faster than the published framerate. It shouldn't affect ENTER_FRAME events though. You should still only get one of those per frame update.
Alternately, are the things you're animating just Sprites and so on, or are you implementing them as Flex components, and trying to redraw them with invalidate() methods and RENDER events and so on?
If you could clarify a few of these points in the question the answer might be clearer. Thanks...
Thanks for the clarifications. If a loaded clip with a animation (I assume you mean a frame animation) is speeding up, then that certainly sounds like something is changing your playback framerate, as opposed to other things that could be going on. With that said it's not a problem I've seen crop up before, but I do think there are some things you could try that ought to narrow down where the problem is:
You might as well try tracing out stage.frameRate during the speed-up. Presumably nothing ought to be changing your framerate, but since that would explain your issues you might as well rule it out.
Try removing as many GUI components as possible and seeing if the problem still occurs, if it's possible to trigger the problem without them.
One sanity check you could try, if it's feasible, is to copy some of the contents of your game into a fresh project and try it there. Sometimes mysterious issues like this happen because some class or SWC is being imported somewhere that everyone forgot about.
You could try driving your code from a different event. For example, as far as I know driving it from Event.EXIT_FRAME or Event.FRAME_CONSTRUCTED ought to look the same, but if it doesn't then that's a hint. Alternately, you could try driving it from something like a keyboard event or MouseEvent.MOUSE_MOVE. Then if updates occur even though you're not firing events, you'll know something else is driving things besides your event loop.
Those are the things I'd try, anyway. Hope you track it down...

Resources