活动窗口后面的Flex打开窗口

时间:2010-07-09 00:45:44

标签: flex air flex4 air2

在Flex Air应用程序中,如何打开活动窗口后面的窗口?

我试过以下,我似乎无法让它工作

<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>

使用此代码,我希望window1在主应用程序窗口后面打开,并且在3秒内,window2将在window1后面打开。但是如果你执行它,window1将在主窗口的顶部打开,window2将在window1的顶部打开,主应用程序将保持焦点。这似乎是Flex中的一个错误。如果有,这个问题是否有解决方法?

2 个答案:

答案 0 :(得分:0)

您是否有特殊原因要将useWeakReference参数设置为true?否则,你应该可以打电话:

timer.addEventListener(TimerEvent.TIMER_COMPLETE, openWindow2);

然而,该行代码中存在一个错误。定时器完成所有周期后,将触发TIMER_COMPLETE事件。您已将计时器设置为无限“触发”。所以它永远不会完成它的循环。

您需要将该行代码修改为以下内容,您应该得到预期的结果:

timer.addEventListener(TimerEvent.TIMER, openWindow2);


<小时/>
解决你的第二个问题(为什么window1不会出现在应用程序后面)。根据orderInBackOf函数的返回值判断:

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

如果窗口不可见,似乎订购失败。可能的情况是,通过在creationComplete处理程序中使用代码,您可以在Application窗口有机会显示自己之前调用此函数。尝试在openWindow2函数中移动该代码。 Yeilding:

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

我希望这在某种程度上有所帮助,

  • gMale

编辑:根据我上次的评论试试这个,

        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);                    
        }

答案 1 :(得分:0)

所以似乎没有一种解决这个问题的好方法。解决方法是为AIREvent.WINDOW_COMPLETE添加事件侦听器并在事件处理程序中移动窗口。这似乎是“正确”的解决方法,它适用于像我的原始示例这样的简单案例。问题是这种方法对我的代码不起作用。

如果你看一下sdk中的spark.components.Window代码,你会看到在打开窗口时添加了Event.ENTER_FRAME的事件监听器(在commitProperties()中)。然后在事件处理程序enterFrameHandler()中,它保留一个计数器,在第二帧上,调度AIREvent.WINDOW_COMPLETE事件。这让我觉得AIREvent.WINDOW_COMPLETE事件将在第二帧触发,无论窗口的状态如何,即使该liveoc说:

  

在Window 完成其初始布局并打开基础NativeWindow 时调度。

我猜我的窗口没有被第二帧完全创建,因此orderInBackOf失败了。


所以这是我的解决方法:

首先,在我的窗口中,我覆盖open(openWindowActive)。如果openWindowActive为false,我为Event.ENTER_FRAME添加一个事件监听器。在事件处理程序中,我保留一个计数器,当帧计数达到一定数量(现在为10)时,我将当前窗口移动到活动窗口后面。这是解决这个问题的一种非常黑客的方法。我一直在增加限制,现在大约90%的时间都成功了。我可以继续增加限制,直到我接近100%,但我讨厌每次对窗口进行任何更改时都要检查这个条件。此情况也可能因机器而异。

如果有人能告诉我我的解决方法有多糟糕,并且告诉我一个更好的方法来解决我的问题,我会很乐意...但在此之前,这将不得不......