我的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打开。标签2尚未构建。
问题是,当我将标签更改为标签2时,Flex需要很长时间来构建标签2 UI组件并显示标签内容。该应用程序在此过程中基本冻结。我需要向用户提供一些指示,他/她需要等待几秒钟。
我尝试使用光标管理器创建繁忙的鼠标图标。这不起作用(例如,只有当Tab 2完成构建时光标才会改变)。
我想在选项卡构建时简单地显示标题窗口。但是,当我切换选项卡时,我不知道如何启动它,以便在Tab 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:
以下大卫的createDeferredContent
评论以及我上一篇文章中关于weltraumpirat的setTimeout
评论,我能够一起解决导致在标签2中的内容显示繁忙光标的解决方案负载。这是我做的:
创建标签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 ms更改为50 ms仍会产生良好的效果。但是将其减少到10毫秒会导致忙碌光标仅在构建和显示所有组件时出现。可以预期,将超时降低到某个阈值以下将导致此类行为。我想知道这个超时值的阈值(例如10到50毫秒之间)是否取决于客户端计算机?或者,如果我使用100毫秒,这是否安全地覆盖所有客户端机器? (我们怎么知道呢?)
(3)我原本希望用setTimeout(start2,100);
替换callLater(start2);
并删除creationPolicy="none"
会产生类似的结果,但事实并非如此(例如繁忙的光标永远不会出现,而且应用程序冻结几秒钟,直到显示选项卡2)。我之前从未使用callLater()
,所以也许我做错了什么(?)。
答案 0 :(得分: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>