Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache flex 在文本区域粘贴大量文本会导致脚本执行超时_Apache Flex_Flash_Performance - Fatal编程技术网

Apache flex 在文本区域粘贴大量文本会导致脚本执行超时

Apache flex 在文本区域粘贴大量文本会导致脚本执行超时,apache-flex,flash,performance,Apache Flex,Flash,Performance,(Flex 3)我有一个TextArea组件,它需要保存用户的剪贴板内容。TextArea在大多数情况下都做得比较好,但是当粘贴大量数据时,由于脚本执行超时,我似乎根本无法获取组件中的内容 我已经做了一个公平的调查,试图并希望找到如何使这项工作。 我发现TextArea正在使用一个IUITextField(在我的例子中,它是运行时TextField的一个实例)来处理获取粘贴数据的工作,然后在完成时抛出一个事件 我没有找到查看TextField源代码的方法,因为它是playerglobal.swc

(Flex 3)我有一个TextArea组件,它需要保存用户的剪贴板内容。TextArea在大多数情况下都做得比较好,但是当粘贴大量数据时,由于脚本执行超时,我似乎根本无法获取组件中的内容

我已经做了一个公平的调查,试图并希望找到如何使这项工作。 我发现TextArea正在使用一个IUITextField(在我的例子中,它是运行时TextField的一个实例)来处理获取粘贴数据的工作,然后在完成时抛出一个事件

我没有找到查看TextField源代码的方法,因为它是playerglobal.swc库中的一个类

有没有一种方法可以让我看到这个类的来源,或者在我的方法中,有没有什么我没有找到的方法来实现这个目标


注:我知道有其他方法可以实现我想要的结果,但我想让这个特定的解决方案起作用。

当大量抗锯齿文本添加到显示列表时,这个问题经常会发生。文本渲染完成后,一切又恢复正常。如果要处理预定义的文本,可以绕过这个问题,方法是将大部分文本拆分为许多小文本,然后将它们逐段添加到后台(例如,一次添加20行文本),每段之间等待一帧,从而允许屏幕刷新

我还没有尝试过这个方法,但是我建议在文本区域中添加一个事件侦听器,如果文本被更改,则检查
event.RENDER
。如果这是真的,则可以删除自上次渲染事件以来添加的所有文本,然后逐帧重新添加,就像上面的示例中那样


此外,尝试使用本机字体而不是嵌入式字体,并关闭抗锯齿,或降低其质量

在Spark文本区域中,粘贴事件将正确触发。也许有一种更干净的方法可以做到这一点,但这就是我找到的解决方案

MXML:


不幸的是,我认为使用Flex3无法截获文本字段上所有类型的用户输入事件

如果您可以切换到Flex 4(因此使用新的FTE),那么您应该在
TextOperationEvent.CHANGING
事件上添加一个侦听器,这是一个可取消的事件。在处理程序中,您可以验证正在添加的文本量,如果文本量过大,则取消事件(
event.preventDefault()
)并将其添加到多个帧中

此事件的好处在于,它也会为事件触发,例如“使用选定文本按delete键”,或剪切/复制/粘贴/删除操作。事实上,我用它来对某种文本字段应用早期验证,我用Flex3无法检测到这种情况

编辑

也许我找到了解决办法。。我注意到,“restrict”属性允许过滤文本字段中允许的字符,它在内置的TextField类中是受支持的,并且它不是包装Flex组件添加的一个特性:对我们的porpuse来说很有趣

因此,我尝试使用它,发现在TextArea上设置
restrict=“
”可以防止在粘贴大量文本时阻塞UI,因为它在播放器级别“早期”应用。好的是,即使使用此设置,TextArea仍将调度
textInput
事件,因此您可以监视粘贴事件并决定如何处理新文本:在一个步骤中更新
text
属性,启动增量更新或忽略事件

复制并粘贴以下代码以查看示例(使用Flex 3.6和Flash Player 11进行测试):



棘手的部分是正确设置textInput事件上的文本,以及大文本的“增量”加载。

由于TextField不希望接受我们的粘贴事件,我们将找到其他人。以下是mx:TextArea解决方案:

MXML:

您还需要在画布的ContextMenu上启用剪贴板项目,并在粘贴完成后将焦点重置为TextArea


从以下位置获得粘贴阻止解决方案:

对于如此大的文本(您提到的文本大约为7MB),这是不可能的

如果查看mx:TextArea的源代码,只需将其TextField text属性设置为您输入的字符串即可插入文本:
从第2050行附近的TextArea.as开始:

 if (textChanged || htmlTextChanged)
    {
        // If the 'text' and 'htmlText' properties have both changed,
        // the last one set wins.
        if (isHTML)
            textField.htmlText = explicitHTMLText;
        else
            textField.text = _text;

        textFieldChanged(false, true)

        textChanged = false;
        htmlTextChanged = false;
    }
如果您使用TextField制作一个示例应用程序,并尝试使用一个大字符串设置其text属性,则会出现脚本超时。(当我尝试使用1MB的字符串长度时,超时):

导入flash.text.TextField;
tf=新文本字段();
addChild(tf);
tf.multiline=true;
tf.wordWrap=true;
宽度=600
tf.高度=500
var-str:String=“”;
对于(VarI:int=0;i200)返回;
微量元素(cnt);
var-str:String=“”;
//一次粘贴大约50K看起来很理想。

对于(var i:int=0;i“大量数据”对于测试来说还不够具体,你想发布一个例子吗?它大约有7mb的文本。我测试了一个简单的文本区域,没有样式,没有处理程序的裸应用程序,我也遇到了同样的问题。也许我应该说,我可能更感兴趣的是一些指针来帮助我自己继续调试这个问题,而不是解决我的问题问题。仅仅从记事本文档中渲染5 mb的纯文本在5分钟内都不会渲染。我说5是因为那是我放弃并结束tast的时候。我强烈建议不要走这条路。你知道,当你设法将7 mb的文本放入文本区域时,整个应用程序会慢得太多,以至于你无法启动是否要执行任何操作?执行诸如输入单个字母或向下滚动之类的操作将导致脚本超时。Event.Render方法不起作用-在我按C键的那一刻之间不会启动任何事件
private var pastedText:String;
private var textPosition:int=0;
//Number of characters to read per frame
private var chunkSize:int=1000;

private function changeHandler(event:TextOperationEvent):void{
    if(String(event.operation)=="[object PasteOperation]"){
        event.preventDefault();
    }
}

private function pasteHandler(event:Event):void{
    pastedText = String(Clipboard.generalClipboard.getData(ClipboardFormats.TEXT_FORMAT));
    this.addEventListener(Event.ENTER_FRAME,frameHandler);
}

private function frameHandler(event:Event):void{
    if( textPosition + chunkSize > pastedText.length ){
        chunkSize = pastedText.length - textPosition;
        this.removeEventListener(Event.ENTER_FRAME,frameHandler);
    }
    textArea.text += pastedText.substr(textPosition,chunkSize);
    textPosition += chunkSize;
}
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    minWidth="955" minHeight="600"
    layout="vertical"
    horizontalAlign="center">

    <mx:Script>
        <![CDATA[

            protected function generateClipboard():void {
                var largeData:String = "";
                while (largeData.length < 1000000) {
                    largeData += "Lorem ipsum ... ";
                }
                System.setClipboard(largeData);
            }

            protected function ontextarea1_textInput(event:TextEvent):void {
                if (event.text.length < 100) {
                    // NAIVE CODE: just to demonstrate that you can
                    // programmatically modify the text.. you should "merge"
                    // the new text with existing content here
                    textArea.text += event.text;
                } else {
                    // do something here, like starting
                    // to add text block by block in
                    // multiple frames
                }
            }

        ]]>
    </mx:Script>

    <mx:TextArea id="textArea" width="100%" height="100%" restrict="" textInput="ontextarea1_textInput(event)"/>

    <mx:Button click="generateClipboard()" label="Set clipboard"/>

</mx:Application>
<mx:Canvas id="canvas" paste="pasteHandler(event)">
    <mx:TextArea id="textArea" textInput="if (event.text.length > 1) event.preventDefault();" 
     keyDown="keyDown(event)" mouseEnabled="false"/>
</mx:Canvas>
private function keyDown(event:KeyboardEvent):void{
    //When CTRL-V is pressed set focus to canvas
    if(event.keyCode==86 && event.ctrlKey)
        canvas.setFocus();
}
 if (textChanged || htmlTextChanged)
    {
        // If the 'text' and 'htmlText' properties have both changed,
        // the last one set wins.
        if (isHTML)
            textField.htmlText = explicitHTMLText;
        else
            textField.text = _text;

        textFieldChanged(false, true)

        textChanged = false;
        htmlTextChanged = false;
    }
   import flash.text.TextField;
    tf = new TextField();
    addChild(tf);
    tf.multiline = true;
    tf.wordWrap = true;
    tf.width= 600
    tf.height = 500
    var str:String = "";
    for (var i:int=0; i<100000; i++) {
        str = str+"0123456789"
    }
    tf.text = str
import flash.text.TextField;
public function test(){
    tf = new TextField();
    addChild(tf);
    tf.multiline = true;
    tf.wordWrap = true;
    tf.width= 600
    tf.height = 500
    addEventListener(Event.ENTER_FRAME,onEF);
}

private var cnt:int = 0;

private function onEF(event:Event):void{
    if (cnt>200) return;
    trace (cnt);
    var str:String = "";
        //pasting around 50K at once seems ideal.
    for (var i:int=0; i<5000; i++) {
        str = str+"0123456789"
    }
    tf.appendText(str);
    cnt++;
}