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

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

问题描述

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



我已经做了一个公平的调查,希望能找到我能做的工作。
我发现TextArea正在使用IUITextField(在我的情况下是运行时的TextField实例)处理获取粘贴数据的工作,然后在完成时抛出一个事件。 b
$ b

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



有没有办法让我可能看到这个类的来源,或者是有什么我失踪的方法来找出一种方法来做到这一点?

PS:我知道会有替代的方式来实现我正在寻找的结果,但我想使这个特定的解决方案的工作。

解决方案

如果你看一下mx:TextArea的源代码,它会插入这样的大文本(你提到文本大约是7MB)。

文本只是将其TextField文本属性设置为您输入的字符串:

从2050行左右的TextArea.as:

  if(textChanged || htmlTextChanged)
{
//如果'text'和'htmlText'属性都改变了,
//最后一组获胜。
if(isHTML)
textField.htmlText = explicitHTMLText;
else
textField.text = _text;

textFieldChanged(false,true)

textChanged = false;
htmlTextChanged = false;





$ b

如果您使用TextField创建示例应用程序并尝试设置其文本属性与一个大字符串,你会得到脚本超时。 (我得到超时,当我尝试它与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

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

唯一可能的解决方案是建立一个自定义的文本框,并逐渐添加文本 - Adob​​e建议使用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 =;
//一次粘贴50K似乎是理想的。
for(var i:int = 0; i< 5000; i ++){
str = str +0123456789
}
tf.appendText(str);
cnt ++;





这个脚本设法将10MB的文本添加到TextField中,增加1MB会变得越来越慢(最后迭代需要大约1秒)。如果你试图用这个文本框来做任何事情(例如调整大小,不用appendText()修改文本,在它完成后将它添加到舞台上...)你将得到脚本超时。因此,完整的解决方案是捕获粘贴事件画布包装技巧(William的解决方案),然后逐渐将文本添加到自定义组件,该组件使用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天全站免登陆