Question

In Flex Air app, how do you open a window behind an active one?

I tried following and i can't seem to get it to work

<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                       xmlns:s="library://ns.adobe.com/flex/spark" 
                       xmlns:mx="library://ns.adobe.com/flex/mx"
                       creationComplete="onCreationComplete(event)">

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            import spark.components.Window;

            private var window1:Window  = new Window();
            private var window2:Window  = new Window();
            private var timer:Timer     = new Timer(3000,1);

            private function onCreationComplete(event:FlexEvent):void
            {
                window1         = new Window();
                window1.title   = "Window 1";
                window1.width   = 200;
                window1.height  = 200;
                window1.open(false);
                window1.orderInBackOf(this);

                window2         = new Window();
                window2.title   = "Window 2";
                window2.width   = 200;
                window2.height  = 200;

                timer.addEventListener(TimerEvent.TIMER_COMPLETE, openWindow2, false, 0, true);
                timer.start();          
            }

            private function openWindow2(event:TimerEvent):void
            {
                window2.open(false);    
                window2.orderInBackOf(window1);
            }
        ]]>
    </fx:Script>
</s:WindowedApplication>

With this code, I would expect window1 to open behind the main app window and, in 3 seconds, window2 would open behind window1. But if you execute this, window1 will open on top of the main window and window2 will open on top of window1 and the main app will retain focus. This seems like a bug in the Flex. If so is there any workaround for this problem?

No correct solution

OTHER TIPS

So it seems like there isn't a good way to solve this problem. A workaround would be to add event listener for AIREvent.WINDOW_COMPLETE and move the window in the event handler. This seems like "correct" workaround and it works for a simple case like my original example. Problem is that this approach did not work on my code.

If you look at the spark.components.Window code from the sdk, you will see that an event listener for Event.ENTER_FRAME is added when opening the window (in commitProperties()). Then in the event handler, enterFrameHandler(), it keeps a counter, and on second frame, dispatch AIREvent.WINDOW_COMPLETE event. This makes me think that AIREvent.WINDOW_COMPLETE event will fire on second frame regardless of the status of the window even though the livedoc says:

Dispatched when the Window completes its initial layout and opens the underlying NativeWindow.

I'm guessing my window wasn't full created by the second frame and therefore orderInBackOf failed.


So here's my workaround:

First, in my window, I override open(openWindowActive). If openWindowActive is false, I add an event listener for Event.ENTER_FRAME. In the event handler, I keep a counter and, when the frame count reaches a certain number (10 right now), I move the current window behind the active one. This is a VERY hacky way to get around this problem. I've been increasing the limit and now it succeeds about 90% of the time. I could continue to increase the limit until I get close to 100% but I hate having to check this condition every time I make any changes to the window. Also this condition could be different depending on the machine.

I would LOVE it if someone can tell me how wrong my workaround is and tell me a much much better way to solve my problem... but till then this will have to do...

Is there a particular reason you're setting the useWeakReference parameter to true? Otherwise, you should be able to just call:

timer.addEventListener(TimerEvent.TIMER_COMPLETE, openWindow2);

However, there's a bug in that line of code. The TIMER_COMPLETE event is fired when the timer is finished all its cycles. You have set your timer to "fire" infinitely. So it will never complete it's cycles.

You need to modify that line of code to the following and you should get your expected results:

timer.addEventListener(TimerEvent.TIMER, openWindow2);




To address your second question (why window1 doesn't appear behind the application). Judging by the return value of the orderInBackOf function:

Boolean  — true if the window was succesfully sent behind;
           false if the window is invisible or minimized. 

It seems that ordering fails if the the window is invisible. It may be the case that, by having the code in the creationComplete handler, you're calling this function before the Application window has a chance to display itself. Try moving that code within your openWindow2 function, as well. Yeilding:

        private function openWindow2(event:TimerEvent):void
        {
            window1.orderInBackOf(this);
            window2.open(false);    
            window2.orderInBackOf(window1);
        }

I hope this helps in some way,

  • gMale

EDIT: per my last comment try this,

        private function openWindow2(event:TimerEvent):void
        {
            window1.depth = 5; //arbitrary number
            window2.depth = 4;
            window1.open(false); //assumes window1 isn't opened before
            window2.open(false);                    
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top