【问题标题】:Flex: how to call titlewindow when changing tab, before tab's UI components are builtFlex:在标签的UI组件构建之前,改变标签时如何调用titlewindow
【发布时间】:2013-01-22 12:41:52
【问题描述】:

我的 Flex4 应用使用如下标签栏:

<s:TabBar id="tabs"/>
    <mx:ViewStack id="vs" height="100%" width="100%">
        <s:NavigatorContent label="Tab 1"  width="100%" height="100%">
            ...
        </s:NavigatorContent>
        <s:NavigatorContent label="Tab 2"  width="100%" height="100%">
            ...
        </s:NavigatorContent>
        <s:NavigatorContent label="Tab 3"  width="100%" height="100%">
            ...
        </s:NavigatorContent>
    </mx:ViewStack>
</s:TabBar>

默认情况下,该应用使用 Tab 1 打开。 Tab 2 尚未构建。

问题是,当我将选项卡更改为选项卡 2 时,Flex 需要很长时间来构建选项卡 2 UI 组件并显示选项卡内容。该应用程序在此过程中基本冻结。我需要向用户提供一些指示,表明他/她需要等待几秒钟。

我尝试使用光标管理器来创建一个忙碌的鼠标图标。这不起作用(例如,光标仅在 Tab 2 完成构建时更改)。

我想在标签构建时简单地显示一个标题窗口。但是,当我切换选项卡时,我不知道如何启动它,这样标题窗口就会出现在选项卡 2 构建之前和期间。

我知道 mx ViewStack 可以具有 change="" 属性,但是当我使用该属性时,直到 Tab 2 完成加载后才会出现标题窗口。

我不确定如何在以下场景中实现callLater() 函数。

谁能帮我弄清楚如何触发标题窗口,以便它在 Tab 2 构建之前和期间出现?

参考资料:

How we implement "Please wait ...." screen in flex when app is busy

Flex: Looking for design pattern to display busy cursor while my app is "busy"

更新 1:

通过下面 David 的 createDeferredContent 评论和 weltraumpirat 在上面链接的上一篇文章中的 setTimeout 评论,我能够拼凑出一个解决方案,导致在加载选项卡 2 中的内容时显示忙碌的光标。这是我所做的:

将 Tab 2 创建为实现以下功能的组件:

<s:VGroup 
    ...
    preinitialize="preinit"
    creationComplete="start1">

    private function preinit():void {
        mx.managers.CursorManager.setBusyCursor();
    }

    private function start1():void {
        setTimeout(start2,100);
    }

    private function start2():void {
        // create mxml components
        myBC.createDeferredContent();

        // place any required actionscript code here
        mx.managers.CursorManager.removeBusyCursor();
    }

    ...

    <s:BorderContainer id="myBC" creationPolicy="none">
        <!--- place all mxml code here to create layout -->
    </s:BorderContainer>

</s:VGroup>

几点说明:

(1) 虽然在 Tab 2 完成构建之前确实会显示忙碌光标,但应用程序仍会冻结,并且当用户移动鼠标时,忙碌光标会停留在屏幕上,而默认鼠标图标(箭头)会在屏幕上移动由用户控制,直到 Tab 2 完成构建并显示。不理想,但至少繁忙的光标表明应用程序正在做某事。如果我愿意,我可以将忙碌光标替换为表示忙碌等的标题窗口。

(2) 将超时时间从 100 毫秒更改为 50 毫秒仍然会产生良好的效果。但是将其减少到 10 毫秒会导致忙碌光标仅在构建和显示所有组件时出现。可以预料,将超时减少到某个阈值以下会导致这种行为。我想知道这个超时值的阈值(例如,在 10 到 50 毫秒之间)是否取决于客户端计算机?或者,如果我使用 100 毫秒,是否可以安全地覆盖所有客户端计算机? (我们怎么知道它会?)

(3) 我原以为用callLater(start2); 替换setTimeout(start2,100); 并删除creationPolicy="none" 应该会产生类似的结果,但它不会(例如,繁忙的光标永远不会出现,应用程序会冻结几秒钟直到显示选项卡 2)。我以前从未使用过callLater(),所以也许我做错了什么(?)。

【问题讨论】:

  • 这不是真正的解决方案,但尝试将 ViewStack 的 creationPolicy 设置为“all”:&lt;mx:ViewStack creationPolicy="all" /&gt;。默认情况下,视图堆栈使用延迟实例化,并且在需要之前不会创建不可见的视图。真正的解决方案是了解为什么您在第二个选项卡中的视图需要这么长时间才能创建。是否愿意展示该代码或描述它在做什么?如果我们了解为什么您的视图需要这么长时间才能创建,我们甚至可以通过使用 callLater(或向您建议的其他想法)的方法为您提供帮助。
  • 将 ViewStack 的 creationPolicy 设置为“all”可以使其更快,但也意味着初始化 APP 需要更长的时间。切换到Tab2的时候除了UI组件和布局搭建还有什么繁重的计算吗?
  • 处理延迟只是因为 Flex 在 Tab 2 中创建和布局各种 UI 组件。这个选项卡涉及很多表单、文本区域和相当复杂的图表。

标签: actionscript-3 apache-flex


【解决方案1】:

如果您在 Tab2 初始化期间有大量计算,您可以将它们分成小块并使用 callLater 机制连续执行它们。

这是一个非常简单的例子:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
           xmlns:s="library://ns.adobe.com/flex/spark" 
           xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
    <![CDATA[
        import mx.core.FlexGlobals;
        import mx.events.FlexEvent;
        import mx.managers.CursorManager;

        private var i:int = 0;

        protected function nc2_initializeHandler(event:FlexEvent):void
        {
            FlexGlobals.topLevelApplication.enabled = false;                
            CursorManager.setBusyCursor();
            callLater(initTab2);
        }

        protected function initTab2():void
        {
            var j:int;

            //Part of calculations
            for (j=0; j< 10000; j++)
            {
                i++;
            }   

            //Check if completed
            if (i<1000000)
            {
                //If not call again
                callLater(initTab2);                    
            }
            else
            {
                //Finished
                CursorManager.removeBusyCursor();
                FlexGlobals.topLevelApplication.enabled = true;
            }
        }

    ]]>
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:VGroup gap="10" top="10" left="10">
    <s:TabBar id="tabs"  dataProvider="{vs}"/>
    <mx:ViewStack id="vs" width="100%" >
        <s:NavigatorContent label="Tab 1"  width="100%" height="100%" >
            <s:Label text="Tab1 content"/>
        </s:NavigatorContent>
        <s:NavigatorContent id="nc2" label="Tab 2"  width="100%" height="100%">
            <s:Label text="Tab2 content" initialize="nc2_initializeHandler(event)"/>
        </s:NavigatorContent>
        <s:NavigatorContent label="Tab 3"  width="100%" height="100%">
            <s:Label text="Tab3 content"/>
        </s:NavigatorContent>
    </mx:ViewStack>

</s:VGroup>

【讨论】:

  • 感谢 David,不幸的是,延迟是由于 Flex 创建 UI 组件并通过 mxml 布局它们,而不是我可以分组以在 initTab2() 等函数中运行的 AS3 代码。除非我可以将 mxml 代码的子集移动到 &lt;fx:Declarations&gt; 块中并使用您的方法以某种方式执行它(例如?)。
  • 可以将mxml声明转换为actionscript函数并连续执行
  • 我的意思是每个 mxml UI 元素都可以在 actionscript 中创建并添加到父级。
  • 如果我将组件设置为invisible,这是否可以节省 Flex 创建/布局的时间?如果是这样,我可以使用callLater() 的方法将组件转回visible。
  • 嗯...我从来没有想过...如果与 includeInLayout 一起使用可以实现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 2020-12-09
  • 2012-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多