在 TextArea 中粘贴大量文本导致脚本执行超时 [英] Pasting a large amount of text in a TextArea leads to a script execution timeout

查看:32
本文介绍了在 TextArea 中粘贴大量文本导致脚本执行超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我在调查方面做了大量的工作,希望能找到如何使这项工作顺利进行.我发现 TextArea 正在使用 IUITextField(在我的情况下是运行时的 TextField 实例)确实处理获取粘贴数据的工作,然后在完成后抛出一个事件.

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

有没有办法让我看到那个类的来源,或者我的方法中是否缺少一些东西来找出使这个工作的方法?

P.S:我知道有其他方法可以实现我正在寻找的结果,但我想让这个特定的解决方案发挥作用.

解决方案

不可能有这么大的文本(你提到文本大约 7MB).

如果您查看 mx:TextArea 的源代码,它会插入文本,只需将其 TextField 文本属性设置为您输入的字符串:
来自 TextArea.as 大约 2050 行:

 if (textChanged || htmlTextChanged){//如果 'text' 和 'htmlText' 属性都改变了,//最后一组获胜.如果(是HTML)textField.htmlText = explicitHTMLText;别的textField.text = _text;textFieldChanged(假,真)文本更改 = 假;htmlTextChanged = false;}

如果您使用 TextField 制作示例应用程序并尝试使用大字符串设置其文本属性,则会出现脚本超时.(当我尝试使用 1MB 的字符串长度时超时):

 import flash.text.TextField;tf = new TextField();addChild(tf);tf.multiline = true;tf.wordWrap = true;tf.width= 600tf.height = 500var str:String = "";for (var i:int=0; i<100000; i++) {str = str+"0123456789"}tf.text = str

这是显示文本的最简单的方法,它会超时.在布局之前,Flex 会尝试用这个文本字段做更多的事情......所以它也会放弃更小尺寸的文本.

唯一可能的解决方案是创建自定义文本字段,并逐渐添加文本 - Adob​​e 建议使用 TextField.appendText():

import flash.text.TextField;公共功能测试(){tf = new TextField();addChild(tf);tf.multiline = true;tf.wordWrap = true;tf.width= 600tf.height = 500addEventListener(Event.ENTER_FRAME,onEF);}私有变量 cnt:int = 0;私有函数 onEF(event:Event):void{如果 (cnt>200) 返回;跟踪(cnt);var str:String = "";//一次粘贴大约 50K 似乎很理想.for (var i:int=0; i<5000; i++) {str = str+"0123456789"}tf.appendText(str);cnt++;}

这个脚本设法将 10MB 的文本添加到 TextField 中...虽然在添加 1MB 后它变得越来越慢(最后迭代大约需要 1 秒).如果您尝试对该文本字段执行任何操作(例如调整大小、不使用 appendText() 修改文本、在完成后将其添加到舞台...),您将收到脚本超时.>

所以完整的解决方案是捕获粘贴事件画布包装器技巧(威廉的解决方案),然后将文本逐渐添加到自定义组件中,该组件使用 appendText 添加文本.(使用 flash.text.TextField,并使用 mx_internal::$addChild() 将其添加到舞台上).我还没有测试过,您是否可以在不触发脚本超时的情况下使用 removeChild 删除由此产生的怪物:).

(Flex 3) I have a TextArea component which needs to hold the user's clipboard content. The TextArea does the job relatively well for most cases but when pasting a large amount of data, I can't seem to get the content in the component at all due to the script execution timeout.

I've done a fair deal on investigation to try and hopefully find how I could make this work. I found that the TextArea is using a IUITextField (which is in my case an instance of TextField at runtime) do handle the job of obtaining the pasting data and then throws an event when it is done.

I have found no way to take a look at the source of TextField as it is a class in the playerglobal.swc library.

Is there a way for me to maybe see the source of that class or is there something I'm missing in my approach to figure out a way to make this work?

P.S: I know there would be alternate way to achieve the results I'm looking for but I would like to make this particular solution work.

解决方案

Its impossible with such large texts (you mentioned that the text is around 7MB).

If you look at the source of mx:TextArea, it inserts text simply be setting its TextField text property to the string you entered:
From TextArea.as around line 2050:

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

If you make a sample app with a TextField and try to set its text property with a large string, you will get script timeouts. (i got timeout when i tried it with a string length of 1MB):

   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

This is the simplest possible way to display text, and it timeouts. Flex will try to do a dozen of more things with this textfield before laying out...so it will give up at much smaller size texts too.

The only possible solution is to make a custom textfield, and add the text gradually - Adobe recommends to use TextField.appendText():

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

This script manages to add 10MB of text into the TextField... although after adding 1MB it gets increasingly slower (it took around 1 sec for an iteration at the end). And if you try to do anything with this textfield (for example resizing, modifying text not with appendText(), adding it to the stage after its complete...) you will get script timeout.

So the complete solution is to capture the paste event canvas wrapper trick (William's solution), and then add the text gradually to a custom component, that uses appendText to add text. (use flash.text.TextField, and add it to the stage with mx_internal::$addChild() ). I have not tested, whether you can remove the resulting monstrosity with removeChild without triggering a script timeout :).

这篇关于在 TextArea 中粘贴大量文本导致脚本执行超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆