[转载]实现Flex的TextArea文本中关键字的高亮显示

2011年12月30日 分类: 开发笔记, Flash

转载实现Flex的TextArea文本中关键字的高亮显示 – STF – 博客园.

最近做的Flex项目中有一个需求,要求在一个TextArea中输入文本时,当文本中出现SQL关键字(如select,from,where等)时,让这些关键字高亮显示。

经过一个下午的研究最终算是基本上实现了,实现的过程就是一个学习的过程。

前几天机器重装了系统,FlexBuilder要重新装,从官网上下了最新版的FlexBuilder4.6装到机器上,算是尝了鲜,不过感觉和4.5差别并不大。接下来便是一步步实现的过程了。

首先要知道使用TextArea的change事件和TextRange类可以动态更改TextArea部分文本的样式。

——————————————–
mx.controls.TextArea.change
当 TextArea 控件中的文本通过用户输入发生更改时分派。使用数据绑定或 ‏‏‎‎ActionScript 代码更改文本时不会引发此事件。

即使 Event.bubbles 属性的默认值是 true,该控件也会在 Event.bubbles 属性设置为 false 时分派此事件。

事件类型:
flash.events.Event.CHANGE
语言版本:
3.0
Player 版本:
Flash 9, AIR 1.1
产品版本:
Flex 3
——————————————–
mx.controls.textClasses.TextRange
TextRange 类提供在 Label、Text、TextArea、TextEditor 和 RichTextEditor 控件中选择和格式化文本范围的属性。
——————————————–
mx.controls.textClasses.TextRange.TextRange(owner:UIComponent, modifiesSelection:Boolean=false, beginIndex:int=-1, endIndex:int=-1)
创建提供文本控件内容子集的新 TextRange Object,包括格式化信息。
参数:
owner 包含文本的控件。此控件必须包含 textField 属性,或者像 RichTextEditor 控件一样包含 textArea属性。
modifiesSelection 是否选择范围中的文本。如果将此参数设置为 true 并且不指定与控件中文本相对应的起始或结束索引,则 Flex 将使用当前文本选项的起始或结束索引。如果此参数为 true,您省略了 beginIndexendIndex参数,并且不存在任何选项,则 TextRange 对象为空。
beginIndex 范围中第一个字符从零开始的索引。如果 modifiesSelection 参数为 false,并且您省略此参数或指定了一个负值,则范围将从第一个文本字符开始。
endIndex 范围中最后一个字符的位置从零开始的索引。如果 modifiesSelection 参数为 false,并且您省略此参数、指定了一个负值或指定的值超出文本结束范围,则范围将以最后一个文本字符结束。
语言版本:
3.0
Player 版本:
Flash 9, AIR 1.1
产品版本:
Flex 3

关键是如何让指定的关键字样式发生变化。首先想到了正则表达式,但由于对正则表达式并不熟悉,所以采取了截取这些字符串,当出现关键字时,更改关键字的样式。

HighlightKeywordTextArea.mxml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<mx:TextArea xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/mx"
            change="textArea_change(event)" width="100%" height="100%" 
            creationComplete="textarea_creationCompleteHandler(event)">
    <fx:Declarations>
        <!-- 将非可视元素(例如服务、值对象)放在此处 -->
    </fx:Declarations>
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;
            import mx.controls.textClasses.TextRange;
            import mx.events.FlexEvent;
            [Bindable]
            public var keyArray:ArrayCollection;
            
            [Bindable]
            public var keyColor:String = "red";
            
            private var tr:TextRange;
            
            private var crlf:String = String.fromCharCode(13);
            
            private var regEx:RegExp = new RegExp(crlf, "g");
            
            private function setKeyColor(num:int,key:String):void
            {
                var text :String = this.text.toUpperCase().replace(regEx," ");
                var str : String = text.substr(num,text.length);
                var strArray : Array = str.split(" ");
                var keyIndex : int = strArray.indexOf(key);
                
                if(keyIndex!=-1)
                {
                    if(keyIndex!=0)
                    {
                        for(var i:int;i< keyIndex;i++)
                        {
                            num += (strArray[i] as String).length+1;
                        }
                    }
                    
                    var length:int = key.length;
                    tr = new TextRange(this, false, num, num + length);
                    tr.color = keyColor;
                    
                    num += (length+1);
                    
                    if(num<text.length)
                    {
                        setKeyColor(num,key);
                    }
                }
            }
            
            private function addTextRange():void{
                try {
                    tr = new TextRange(this);
                    tr.color = "black";
                    tr.textDecoration = "normal";
                    tr.fontSize = 20;
                    for each(var key:String in keyArray)
                    {
                        setKeyColor(0,key);
                    }
                    
                } catch (err:RangeError) {
                    
                }
            }
            
            private function textArea_change(evt:Event):void {
                
                addTextRange();
            }
            
            protected function textarea_creationCompleteHandler(event:FlexEvent):void
            {
                addTextRange();
            }
            
        ]]>
    </fx:Script>
</mx:TextArea>

测试主程序HLKeyTaTest.mxml如下:

<?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" xmlns:components="com.stf.components.*">
    <fx:Declarations>
        <!-- 将非可视元素(例如服务、值对象)放在此处 -->
    </fx:Declarations>
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;
            
            [Bindable]
            public var keyArray : ArrayCollection = new ArrayCollection(["AS","SELECT","FROM","WHERE","AND","OR"]);
            
        ]]>
    </fx:Script>
    <components:HighlightKeywordTextArea width="500" height="300"
        keyColor="red" keyArray="{keyArray}"
        text="select name as 姓名 from user_info where id='key'">
        
    </components:HighlightKeywordTextArea>
</s:Application>

测试效果如下:

还存在一些问题:

1.对于很长很长的文本,字符串截取比对效率有点低,有点卡。

2.对于SQL的语的处理还有点弱,比如在引号中如果出现SQL关键字时同样会高亮显示,要是实现SQL编辑中的效果还差的有点远。


标签: , ,
本文的评论功能被关闭了.
备案信息冀ICP 0007948