I'm puzzled about whether the visible property of DisplayObject is:
an indication from Flex of whether the display object is visible.
an instruction to Flex to display the display object.
I'm asking because I'm automating some Flex tests using Flex Pilot, and I need to know for certain when a display object becomes clickable. In the application I'm testing, clickable seems to mean rendered.
Given the nature of the application and my tests, I don't think it's feasible to watch for the updateCompleted event. I need a way to detect whether the display object is visible based on the values of its properties and its containers' properties at a given moment.
I understand that even if a display object's visible property is true, it will be visible only if all of its containers are also visible. This means that I'll have to extend Flex Pilot by writing an ActionScript method to determine whether the display object and its containers all have visible=true. But I'm concerned that even that method won't tell me for sure that the display object is really rendered, and therefore clickable.
My puzzle comes from reading two descriptions from Adobe.
The "About creating advanced components" document suggests that the visible property is set by Flex after the display object is rendered. In this description, it is Flex's job to set the value,
so that value is thus an indication from Flex of whether the display object is visible.
On the other hand,
Adobe's description of the visible property suggests that the property is writable. And the code sample suggests that if the application changes the value, Flex will respond by displaying or hiding the display object. In this description, the application sets the value as an instruction to Flex to display the object. I'm guessing that in this case Flex re-renders the display object (if visible changes from false to true) or its container (if visible changes from true to false).
So two main questions:
Is the visible property used in both of these ways, both as an indication from Flex about the display object's visibility and an instruction to Flex about whether to display the object?
If the application changes visible from false to true, when does the display object actually become visible? Is it visible by the time the setter returns? Or does setting the property merely schedule the object to become visible during some later event? If it's the latter, that means there may be a duration during which visible is true, but the display object has not yet been rendered. If that's the case, I'm at a loss for how to determine, from the state of the display objects at a given instant, whether a display object has been rendered.
There are some key constraints for a DisplayObject to be rendered. First of all, it has to be in the display list. visible has to be set to true, otherwise it would be ignored from the rendering. The last key aspect is the so called elastic race track which basically describes when event handling, code execution and rendering occur. So, implementing event handlers for FlexEvent.UPDATE_COMPLETE is not so wrong, because those are dispatched when ever a property changes, which change the rendered representation of the component on the screen.
Is the visible property used in both of these ways, both as an indication from Flex about the display object's visibility and an instruction to Flex about whether to display the object?
Yes, the visible property is initially set to true by the framework before FlexEvent.CREATION_COMPLETE is dispatched, so the Flash player won't draw the component in a state (i don't mean the Flex view states), which is some where between construction and having the complete initialized view.
If the application changes visible from false to true, when does the display object actually become visible? After the next render cycle happend.
Related
I have a set of QML items distributed all over my UI. They display data from a remote device and their content needs to be updated regularly. The Items are spread on several tabs and hidden in nested ListView instances, so most of them won't be visible to the user all the time.
In order to keep the bandwidth low I want to update only those items that are currently visible to the user.
I am looking for the right hook to get the information which of these Items is currently displayed from within the Item, without relying on information from the parents. If they were all placed in ListView delegates I could use the delegate's Components onCompleted and onDestroyed signals. Since this is not the case I am stuck at finding out how to get this information.
Am I missing something here? Is there an onPaintFinished signal or something similar? My workaround would be to add that logic to the parent containers, but that would be tedious, since there are several kinds of container that can contains these display Items.
Instances that are on delegates of a ListView will not exist until they would be in the visible range or the cache range around the visual area of the list view. If the delegate moves outside of that range, it is destroyed. So, no need to worry about instances hidden there.
Furthermore, items are currently not visible are also not drawn. They are not entered into the scene graph, and hence, not rendered. So, instances of your items appearing on tabs that are currently not current will also not be drawn. However, these items do still exist of course.
Figuring out if an item is effectively visible or not is quite a hard problem though. QML delegates part of that to OpenGL (clipping for instance). There is not feedback on the result of that. You could in theory lift that information out of the renderer, but that would require customizing that and that is very hard. You could take a look at the heuristics that GammaRay uses to warn about items not being visible. Perhaps you can take some inspiration from that.
I need to completely initialize a custom component in my Flex app (i.e. I should be able to access it from action script and get its properties and its children etc), But I do not want to add it to the display or make it visible.
I have tried to add it to my visible component, but keep it visible, but often many of its properties are set only when it is drawn, so i don't get what i need.
Is there a way to add a custom component to some sort of 'Virtual' display, that is not visible to the user?
You could add the component to an invisible Sprite - that way the component itself could both be on the stage and have its own visible property set to true.
Did you try using initialize()? After a view is added to the display list, the initialization stage begins. Calling initialize() before addChild() should let you initialize the view without needing to first add it to the stage.
For more info visit:
http://flexscript.wordpress.com/2008/10/24/flex-component-lifecycle-and-flex-component-framework/
http://blog.deadinkvinyl.com/2008/10/05/flex-3-addchild-and-initialize/
Not sure if possible without adding it to the display list, although I'd wish it were to some extent.
I once had to make custom drag proxy, which didn't work with the real component, because of some weird skinning issues. So instead I had PopupMananger add a box as a popup, added my component to the box, called validateNow on the component, drew it in a bitmap data, removed the popup, and used the bitmap data as the proxy.
So what you were trying was missing a call to validateNow most likely.
Flex application is being made accessibility compliant. When a custom component is made visible based on some condition, the first item (either text or formitem or textarea) inside the component is skipped by Jaws. It reads from the second item. On pressing UP arrow, the first item is then read.
Is there a way to make the first item accessible without need for pressing UP arrow?
This is likely going to be related to focus management.
You're likely going to want to assign componentId.setFocus() to the first component in the current view when the view state changes.
You need to re-assess the focus when the state of your display changes. If you post how you are managing display state I can suggest exactly how to trigger that via an event or in your custom state method.
Also, if that doesn't work, try this once your screen is ready / state changed :
focusManager.moveFocus(mx.events.FocusRequestDirection.TOP);
What is the best way to render to a UIComponent which hasn't been added to the stage? (I'm using UIComponents as renderers for objects, and want to render new copies for image export, filtering, etc.)
Two strategies I've seen/used so far include realizing the component to ensure it calls all the lifecycle methods:
Add the component to Application.application, render with BitmapData.draw(), remove component. This is similar to what I've seen done for printing unrealized components as well.
Add the component to a pop up window, render with BitmapData.draw(), dismiss popup after rendering complete.
I believe both of these just rely on the UI not refreshing while the current thread/event is executing, though (1) could also rely on the component being realized out of view.
Is there a better way?
What I've used in the past with much success is the following:
Create a new instance of your component
Add an event listener for FlexEvent.CREATION_COMPLETE
Set visible=false on the component
Add the component as a child of the main Application
When the component is created, the event listener function will be invoked. The rest of the logic should be put in / invoked from your event listener function
Remove the event listener you added in step #2.
Use ImageSnapshot.captureImage() or captureBitmapData() to capture the visual representation of the component.
Remove the component from the main Application
Process the image data as you need to.
I've used this to snapshot various Flex charting components for use in PDF's generated on the server side. After getting the BitmapData I use the PNGEncoder or JPEGEncoder classes to compress the data, then encode it in Base64 before uploading to the server.
I'm pretty sure you can use the draw() method in BitmapData without having your component on the DisplayList.
For example is use it when I need to modify images I load with the Loader Class. In the init handler I create a BitmapData instance and draw the Bitmap from the loadInfo.content property, then copyPixels() or whatever I need to modify the loaded image
So much of a UIComponent's layout can be tied to it's context. This is especially true for a lot of its derivatives (e.g. HBox) since the fluidity of the layout is tied to it's parent's size and the number of siblings sharing its parents space.
Additionally Flex can be a real pain to get to visually update. Often critical render functions aren't done synchronously ... there are callLater, callLater2 and other hacky approaches that make dealing with the auto-magical layout properties of UIComponents a major headache. Not even calling validateNow or updateDisplayList can guarantee that the layout will be correct on the current frame (instead of a few frames in the future).
I suggest the best thing you can do is not use a UIComponent and try and use a Sprite or other.
Your approach to attach it but make it invisible (alpha = 0, mouseEnabled = false, mouseChildren = false) is decent. You should listen for the FlexEvent.CREATION_COMPLETE callback before you are certain it is properly laid out. Then you can bitmapData.draw it and then remove it from the stage. If you must use UIComponents then I know of no better way.
You can call the lifecycle function manually before using the BitmapData.draw(). Do the following.
createChildren().
commitProperties().
updateDisplayList().
bmd.draw().
The first 2 steps are not 100% necessary, you can put all codes into updateDisplayList(). Because you invoke the function manually, you don't have to worry this is invoked by Flex framework many times.
I'm having some troubles with Flex with regards to changing controls on different viewstack panels. At runtime, certain controls aren't accessible and come back as null. Here's an example structure:
viewstack1
canvasPeople
datagridPeople
canvasDetails
tabNavigator1
canvasPersonDetail
txtLastname
canvasPersonOptions
comboboxOccupation
I have a "click" handler in datagrid1 set up to activate canvasB (viewstack1.selectedChild = canvasB) and the detail options box (tabNavigator1.selectedChild = canvasPersonOptions). The former works OK but the latter returns an error about accessing a null object, because at the moment the user clicks on an item in the People datagrid, the tabNavigator1 is null, as is any control underneath it. (its parent, though (canvasDetails), is addressable.) Currently this is a tiny application, so it's not like it's waiting to load the items. Is there a way to control how Flex renders controls so they're accessible before the user sees them? I don't know if this is specific to the viewStack control.
Yes, this is referred to as "creation policy" and it's a property on all Container classes. To do what you we're looking for, you can use a creation policy of "all"; "auto" is the default.
A creationPolicy of ContainerCreationPolicy.AUTO means that the container delays creating some or all descendants until they are needed, a process which is known as deferred instantiation. This policy produces the best startup time because fewer UIComponents are created initially. However, this introduces navigation delays when a user navigates to other parts of the application for the first time. Navigator containers such as Accordion, TabNavigator, and ViewStack implement the ContainerCreationPolicy.AUTO policy by creating all their children immediately, but wait to create the deeper descendants of a child until it becomes the selected child of the navigator container.
A creationPolicy of ContainerCreationPolicy.ALL means that the navigator containers immediately create deeper descendants for each child, rather than waiting until that child is selected. For single-view containers such as a VBox container, there is no difference between the ContainerCreationPolicy.AUTO and ContainerCreationPolicy.ALL policies.
More info here:
http://livedocs.adobe.com/flex/3/html/layoutperformance_04.html
Be careful with this though: Flex picked AUTO as the default for a reason. If your app grows large, the initialization time under creationPolicy=all will be large.
The creation of subcomponents is controlled by the creationPolicy property. It is described in detail in the Flex 3 documentation page "About the creationPolicy property".
If you set the property to "all", every subcomponent of the ViewStack container will be created as soon as the ViewStack is created. The same works for the TabNavigator. Of course this might have some performance implications, which are also described in the documentation.