AS3,如何显示动态文本的最后一行(以及更多)?

时间:2010-07-28 01:09:58

标签: flash actionscript-3

我制作了一个动作脚本,用于加载外部文本文件,并将其内容滚动到底部:

var myTextLoader:URLLoader = new URLLoader();
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);

function onLoaded(e:Event):void {
track_info.text = e.target.data;

addChild(track_info);
  addEventListener(Event.ENTER_FRAME, scrollField);
}

function scrollField(e:Event):void {
 if(track_info.scrollV < track_info.maxScrollV) {
    track_info.scrollV++;
  }else{
removeEventListener(Event.ENTER_FRAME, scrollField);
  }
}

myTextLoader.load(new URLRequest("tracks.txt"));

tracks.txt是一个软件的日志文件,该软件以这种格式实时从播放器中获取mp3艺术家和歌曲名称标签(无法更改)。当前歌曲位于列表的底部。每首歌曲以“[Day-Month-Year Hour:Min:Sec] *”(25个字符前缀)开头:

[14-07-2010 20:21:33] Log file created for client.
[14-07-2010 20:21:33] Client connected.
[14-07-2010 20:26:21] * Artist 21 - Song 11
[14-07-2010 20:40:02] * Artist 42 - Song 02
[14-07-2010 20:45:04] * Artist 14 - Song 10
[14-07-2010 20:47:19] * Artist 46 - Song 04
[14-07-2010 20:51:09] * Artist 07 - Song 09
[14-07-2010 20:54:13] * Artist 54 - Song 01
[14-07-2010 20:57:32] * Artist 19 - Song 12
[14-07-2010 21:00:51] * Artist 35 - Song 06
[14-07-2010 21:04:02] * Artist 43 - Song 08

该脚本有效,但我想知道这个问题是否可以解决:

  1. 我想在flash电影中只显示当前歌曲,列表的最后一行(正在播放的那一行),而不是tracks.txt文件中的所有数据。可以吗?

  2. 为此,电影必须几乎实时地从.txt中自动更新内容以将新歌曲信息显示到文本字段中,替换前一个。有没有办法做到这一点?

  3. 最后,是否可以隐藏文本字段中的“[Day-Month-Year-Hour:Min:Sec] *”25个字符前缀,以便仅显示flash电影中的Artist-Song Name部分?

  4. 提前感谢您的帮助。

    修改

    var reload:Timer = new Timer(5000, 0); 
    reload.addEventListener(TimerEvent.TIMER, onTimer); 
    function onTimer(event:TimerEvent):void{ 
        var myTextLoader:URLLoader = new URLLoader(); 
        myTextLoader.addEventListener(Event.COMPLETE, onLoaded); 
        function onLoaded(e:Event):void {
            var lines:Array = e.target.data.split("\n"); 
            var lastLine:String = lines[lines.length - 1]; 
            var artistAndSong:String = lastLine.substr(24); 
            track_info.text = artistAndSong; 
            addChild(track_info); 
            myTextLoader.load(new URLRequest("tracks.txt")); 
        } 
        reload.start(); 
    }
    

    修改

    也许split()不适用于真正的.log文件。显示所有文本,而不仅是最后一行。这是.log示例:

    [30-07-2010 03:21:34] Log file created for client "127.0.0.1,55684".
    [30-07-2010 03:21:34] Client "127.0.0.1,55684" connected and has been identified as Traktor (or a something close enough).
    [30-07-2010 03:22:58] * The Bravery - An Honest Mistake
    [30-07-2010 03:23:22] * The Waterboys - The Whole of the Moon
    

    修改

    var reload:Timer = new Timer(5000, 1); 
    reload.addEventListener(TimerEvent.TIMER, onTimer); 
    
    var tracksLoader:URLLoader = new URLLoader();
    tracksLoader.addEventListener(Event.COMPLETE,onTracksLoaded);
    tracksLoader.addEventListener(IOErrorEvent.IO_ERROR,onTracksError);
    tracksLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onTracksError);
    
    loadTracks();
    
    function onTracksLoaded(e:Event):void {
        trace("onTracksLoaded");
        parseTracks(tracksLoader.data); 
        reload.start(); 
    }
    
    function onTimer(event:TimerEvent):void{ 
        loadTracks();
    }
    
    function onTracksError(e:Event):void {
        trace("onTracksError", e);
        reload.start();
    }
    
    function loadTracks():void {
        tracksLoader.load(new URLRequest("127.0.0.1,55684.log")); 
    }
    
    function parseTracks(data:String):void {
        try {
            debugChars(data); 
            var lines:Array = data.split("\r\n"); 
            var lastLine:String = lines[lines.length - 1]; 
            var artistAndSong:String = lastLine.substr(24).split(" - ").join("\n");
            trace(artistAndSong);
            track_info.text = artistAndSong; 
            addChild(track_info);
        } catch(e:Error) {
    
        }
    }
    
    function debugChars(str:String):void {
        var buffer:ByteArray = new ByteArray();
        buffer.writeUTFBytes(str);
        buffer.position = 0;
        var result:String = "";
        while(buffer.bytesAvailable) {
            result += "0x" + uint(buffer.readUnsignedByte()).toString(16) + ", ";
            if(buffer.position % 16 == 0) {
                result += "\n";
            }
    
        }
        //  print this string...
        trace(result);
    }
    

    修改

    请注意,“艺术家”和“歌曲名称”之间的换行符是由以下代码引起的:

    .split(" - ").join("\n");
    

    .log实际上带有'Artist - Song Name'。

    onTracksLoaded
    0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x31, 0x30, 0x20, 0x30, 0x33, 0x3a, 0x32, 
    0x31, 0x3a, 0x33, 0x34, 0x5d, 0x20, 0x4c, 0x6f, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x63, 
    0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 
    0x74, 0x20, 0x22, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2c, 0x35, 0x35, 0x36, 
    0x38, 0x34, 0x22, 0x2e, 0xa, 0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x31, 0x30, 
    0x20, 0x30, 0x33, 0x3a, 0x32, 0x31, 0x3a, 0x33, 0x34, 0x5d, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 
    0x74, 0x20, 0x22, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2c, 0x35, 0x35, 0x36, 
    0x38, 0x34, 0x22, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 
    0x64, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 
    0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x54, 0x72, 0x61, 0x6b, 0x74, 0x6f, 0x72, 
    0x20, 0x28, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 
    0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x29, 0x2e, 0xa, 
    0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x31, 0x30, 0x20, 0x30, 0x33, 0x3a, 0x32, 
    0x32, 0x3a, 0x35, 0x38, 0x5d, 0x20, 0x2a, 0x20, 0x54, 0x68, 0x65, 0x20, 0x42, 0x72, 0x61, 0x76, 
    0x65, 0x72, 0x79, 0x20, 0x2d, 0x20, 0x41, 0x6e, 0x20, 0x48, 0x6f, 0x6e, 0x65, 0x73, 0x74, 0x20, 
    0x4d, 0x69, 0x73, 0x74, 0x61, 0x6b, 0x65, 0xa, 0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 
    0x30, 0x31, 0x30, 0x20, 0x30, 0x33, 0x3a, 0x32, 0x33, 0x3a, 0x32, 0x32, 0x5d, 0x20, 0x2a, 0x20, 
    0x54, 0x68, 0x65, 0x20, 0x57, 0x61, 0x74, 0x65, 0x72, 0x62, 0x6f, 0x79, 0x73, 0x20, 0x2d, 0x20, 
    0x54, 0x68, 0x65, 0x20, 0x57, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 
    0x20, 0x4d, 0x6f, 0x6f, 0x6e, 0xa, 0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x31, 
    0x30, 0x20, 0x30, 0x33, 0x3a, 0x32, 0x37, 0x3a, 0x35, 0x36, 0x5d, 0x20, 0x2a, 0x20, 0x42, 0x61, 
    0x62, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x2d, 0x20, 0x59, 0x65, 0x67, 0x75, 
    0x61, 0xa, 
    g file created for client "127.0.0.1,55684".
    [30-07-2010 03:21:34] Client "127.0.0.1,55684" connected and has been identified as Traktor (or a something close enough).
    [30-07-2010 03:22:58] * The Bravery
    An Honest Mistake
    [30-07-2010 03:23:22] * The Waterboys
    The Whole of the Moon
    [30-07-2010 03:27:56] * Babasonicos
    Yegua
    

2 个答案:

答案 0 :(得分:3)

对于1)和3),String::split将会这样做。

这将是:

/* 
\n is the end of line character. Depending on the program that creates
the text file, you might need to change it to \r\n or \r
Note I'm not doing any error checking, you might want to add it...
*/
var lines:Array = e.target.data.split("\n");
var lastLine:String = lines[lines.length - 1];

如果格式已修复,您可以将最后一行拆分为“*”,甚至可以使用substr来获取艺术家和歌曲名称。

/*
Again, I'm not checking for any errors
*/
var songAndArtist:String = lastLine.split("*")[1];

var songAndArtist:String = lastLine.substr(25);

对于2),只需以合理的间隔轮询服务器。有几种方法可以做到这一点。一个可能是,无论何时加载文件,都可以开始Timer;完成此计时器后,停止计时器并重新加载文件。您也可以使用setTimeout代替计时器。

修改

不确定您发布的代码存在什么问题,但解析日志的部分对我来说很好。我重新调整了一下,并在加载数据期间添加了错误检查。

您的代码存在一个问题:在等待当前加载操作完成之前调用计时器。这可能会导致问题。您不需要同时进行两次下载,因此在尝试重新加载之前最好等待下载完成(成功或不成功)(您可能不想尝试重新加载错误;或者可能限制您的重试为2,3或类似的东西,但这取决于你)。

另外,请注意我将计时器的重复次数更改为1,因此您无需停止计时。这意味着它将运行一次,然后它将停止,直到您再次调用start)。我构造了一些代码,将其部分分成不同的函数,因此更容易理解。

在parseTracks函数中,我将所有代码包装在try / catch中,几乎可以捕获所有错误。这有点快速和肮脏,所以我一般不推荐那种错误处理方式,但可能会在这里完成工作。

var reload:Timer = new Timer(5000, 1); 
reload.addEventListener(TimerEvent.TIMER, onTimer); 

var tracksLoader:URLLoader = new URLLoader();
tracksLoader.addEventListener(Event.COMPLETE,onTracksLoaded);
tracksLoader.addEventListener(IOErrorEvent.IO_ERROR,onTracksError);
tracksLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onTracksError);

loadTracks();

function onTracksLoaded(e:Event):void {
    trace("onTracksLoaded");
    parseTracks(tracksLoader.data); 
    reload.start(); 
}

function onTimer(event:TimerEvent):void{ 
    loadTracks();
}

function onTracksError(e:Event):void {
    trace("onTracksError", e);
    reload.start();
}

function loadTracks():void {
    tracksLoader.load(new URLRequest("tracks.txt")); 
}

function parseTracks(data:String):void {
    try {
        var lines:Array = data.split("\n"); 
        var lastLine:String = lines[lines.length - 1]; 
        var artistAndSong:String = lastLine.substr(24); 
        trace(artistAndSong);
    } catch(e:Error) {

    }
}

修改2

添加此功能并打印其结果以尝试检测所涉及的字符是否存在问题...从parseTracks中调用它,如下所示:

debugChars(data);


function debugChars(str:String):void {
    var buffer:ByteArray = new ByteArray();
    buffer.writeUTFBytes(str);
    buffer.position = 0;
    var result:String = "";
    while(buffer.bytesAvailable) {
        result += "0x" + uint(buffer.readUnsignedByte()).toString(16) + ", ";
        if(buffer.position % 16 == 0) {
            result += "\n";
        }

    }
    //  print this string...
    trace(result);
}

答案 1 :(得分:1)

而不是进行字符串拆分我建议使用一些正则表达式匹配字符串

var $lastLine:String = String(e.target.data).match(/.*$/);

你也可以得到最后一行减去方括号[^]]*$中的任何内容 - 但如果艺术家的名字中有一个],这可能会制动,但是我会使用这个表达式从$lastLine无论如何

然后你可以使用

var $artistAndSong:String = $lastLine.match(/\*.*/);

这将匹配第一个*

之后的任何内容

如果你用正则表达式玩一点,你可以摆脱它,但总是有助于使用像http://regexpal.com/这样的东西