2

在 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 中的一个错误。如果是这样,这个问题有什么解决方法吗?

4

2 回答 2

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 处理程序中,您在应用程序窗口有机会显示自身之前调用了此函数。尝试在您的 openWindow2 函数中移动该代码。屈服:

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

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

编辑:根据我最后的评论试试这个,

        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);                    
        }
于 2010-07-09T03:29:12.380 回答
0

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

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

当 Window完成其初始布局并打开底层 NativeWindow时调度。

我猜我的窗口不是由第二帧创建的,因此 orderInBackOf 失败了。


所以这是我的解决方法:

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

如果有人能告诉我我的解决方法有多么错误并告诉我一个更好的方法来解决我的问题,我会很高兴......但在那之前,这将不得不做......

于 2010-07-10T01:25:52.703 回答