麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

MIDP終端模擬之二:高級終端模擬

2019-11-18 16:11:13
字體:
供稿:網(wǎng)友

下載 項(xiàng)目源代碼

在本系列的第一篇文章中,我們構(gòu)建了一個(gè)簡單的可在任何支持 TCP/ip 插槽的 MIDP 設(shè)備上運(yùn)行的終端模擬器。它包含一個(gè)實(shí)現(xiàn) Telnet 協(xié)議的 Connection 和一個(gè)經(jīng)過定制來顯示終端內(nèi)容的 Canvas。在第二篇文章中,我假定您已經(jīng)閱讀了第一篇文章并熟悉了這些組件

MIDP終端模擬之二:高級終端模擬(圖一)現(xiàn)在我們將進(jìn)一步加強(qiáng)這個(gè)應(yīng)用程序。首先,我們將通過添加一個(gè)更高級的終端類型來增加一些復(fù)雜性。然后我們將添加對用戶輸入的支持——注意大多數(shù)移動(dòng)設(shè)備的各種限制。完成后,我們就能夠使用這個(gè)應(yīng)用程序來通過 Telnet 連接到遠(yuǎn)程服務(wù)器并運(yùn)行許多種類的程序,而這一切都是從您的 MIDP 設(shè)備來進(jìn)行的。

關(guān)于 ANSI 終端

在上一篇文章中我們實(shí)現(xiàn)了一個(gè)“啞巴”終端。它顯示的僅僅是一個(gè)字符流,當(dāng)進(jìn)入的字符到達(dá)屏幕的邊緣時(shí)就換行到下一行,在遇到一個(gè)換行符時(shí)就跳到下一行。雖然這種程度的交互性對于整代的命令行應(yīng)用程序是足夠的,但較復(fù)雜的軟件則將屏幕作為一個(gè)整體來處理,這就需要編寫和清除特定位置的字符以提供更好的用戶體驗(yàn)。

這里有一段有趣的歷史。在 20 世紀(jì) 70 年代,眾多生產(chǎn)視頻終端的廠商提供的屏幕操縱功能專有且各不相同,并以不兼容的方式來實(shí)現(xiàn)。要編寫可利用多種這樣的設(shè)備的面向屏幕的軟件就很困難。

American National Standards Institute (ANSI) 參與進(jìn)來。堅(jiān)持其通過可互操作性來支持商業(yè)的要求,ANSI  介入并發(fā)布了標(biāo)準(zhǔn) X3.64:Additional Controls for Use with American National Standard Code for Information Interchange。這個(gè)文件定義了現(xiàn)在所知的 ANSI 終端類型。它對將光標(biāo)移動(dòng)到屏幕上的特定位置、在光標(biāo)位置插入和刪除字符都規(guī)定了標(biāo)準(zhǔn)的命令序列。

最為重要的是命令序列定義自身,因?yàn)榧词故俏磳?shí)現(xiàn)所有命令的終端也至少能夠?qū)⒉恢С值拿钭R別為命令,并安全地忽視它們。這一進(jìn)步使得軟件開發(fā)商可以按照通用標(biāo)準(zhǔn)來編寫,并確信他們的應(yīng)用程序能夠至少占用較小的容量來在很多廠商的設(shè)備上運(yùn)行。ANSI 的故事是軟件行業(yè)一個(gè)重復(fù)出現(xiàn)的主題的一個(gè)很好的例子:采用一種標(biāo)準(zhǔn)會(huì)極大地?cái)U(kuò)展可互操作性。

ANSI 終端標(biāo)準(zhǔn)是一種很像 Telnet 協(xié)議的協(xié)議。它定義了多個(gè)特殊的字符序列,使一個(gè)應(yīng)用程序可區(qū)分要解釋的命令和要顯示到屏幕的數(shù)據(jù)。

ANSI 終端是我們將要模擬的終端類型。TelnetConnection 已經(jīng)在其到達(dá)屏幕之前過濾出 Telnet 握手和協(xié)商;現(xiàn)在我們將增加另一個(gè)過濾器來過濾出并解釋 ANSI 命令。因?yàn)檫@些命令是我們的終端的指令,實(shí)現(xiàn)該邏輯的最好的地方就是在 TelnetCanvas 類自身中。

終端轉(zhuǎn)義序列如何工作?

當(dāng) Telnet 使用字節(jié)值 255 來以信號方式表示一個(gè)命令序列時(shí),ANSI 使用 ASCII 轉(zhuǎn)義序列,其值是 27。ANSI 將如下工作:

我們從輸入讀取一個(gè)字節(jié)。如果其值不是 27 (ESC),則它不是一個(gè)命令∶我們將它直接送到應(yīng)用程序并繼續(xù)讀取。

我們讀取下一個(gè)字節(jié)。如果其值不是 133 ([),則它不是一個(gè)命令;我們將該字節(jié)后所跟的 27 直接送到應(yīng)用程序并繼續(xù)讀取。

我們將繼續(xù)讀取,直到讀取到大于 63 的一個(gè)字節(jié)。這些字節(jié)形成一個(gè)字符串,其中含有命令的參數(shù)。最后一個(gè)字節(jié)(是 64 或更大)是命令代碼。我們處理(或忽略)該命令并繼續(xù)讀取。

許多命令從官方來講是標(biāo)準(zhǔn)的一部分。雖然完全模擬是一個(gè)值得的目標(biāo),我們?nèi)詫⒕Ψ旁讷@得足夠的功能來使眾多軟件可以接受地運(yùn)行。我們將實(shí)現(xiàn)以下命令:

Cursor Control SequencesErase SequencesA Move cursor up n lines@ Insert n blank spacesB Move cursor down n linesJ Erase display: after cursor (n=0), before cursor (n=1), or entirely (n=2).C Move cursor forward n spacesD Move cursor backward n spacesK Erase line: after cursor (n=0), before cursor (n=1), or entirely (n=2). G Move cursor to column xH Move cursor to column x, row yL Insert n new blank linesd Move cursor to row yM Delete n lines from cursors Save current cursor positionP Delete n characters from cursoru Return to saved cursor position 


大多數(shù)這些命令期望參數(shù)采用分號分割字符串的形式。參數(shù)出現(xiàn)在序列 ESC [ 后和命令字節(jié)前。例如,一條用于將光標(biāo)移動(dòng)到第 10 行和第 10 列的命令將如下所示:ESC [ 1 0 ; 1 0 H。許多命令只帶一個(gè)參數(shù);例如,ESC [ 2 J 將清除屏幕顯示。漏掉的參數(shù)將默認(rèn)為 1,所以 ESC [ H 將把光標(biāo)返回到坐標(biāo) (1,1),而 ESC [ B 則將光標(biāo)移動(dòng)到下一行。

雖讓有很多的東西要處理,但協(xié)議卻相當(dāng)簡單。

增強(qiáng) Telnet Canvas 類

我們需要在兩個(gè)領(lǐng)域中更新 TelnetCanvas。它需要解釋從遠(yuǎn)程主機(jī)接收的 ANSI 命令并發(fā)送 ANSI 命令來響應(yīng)用戶輸入。對于輸入,我們將允許用戶使用設(shè)備上的鍵盤來移動(dòng)光標(biāo)。

實(shí)現(xiàn) ANSI

雖然我們必須修改 TelnetCanvas 類的內(nèi)部,但卻沒有必要更改公共接口。所有數(shù)據(jù)將仍由 receive() 方法來接收。我們只更改其實(shí)現(xiàn)來監(jiān)視轉(zhuǎn)義序列:

/*** Appends the specified ascii byte to the output.*/public void receive( byte b ){    // ignore nulls    if ( b == 0 ) return;     if ( state == PARAMS_STATE )    {        // if still receiving parameters        if ( b < 64 )        {            argbuf[0]++;                        // grow if needed            if ( argbuf[0] == argbuf.length )            {                char[] tmp = new char[ argbuf.length * 2 ];                System.arraycopy(                     argbuf, 0, tmp, 0, argbuf.length );                argbuf = tmp;             }                        argbuf[ argbuf[0] ] = (char) b;        }        else // final byte: PRocess the command        {            processCommand( b );            // reset for next command            argbuf[0] = 0;            state = NORMAL_STATE;        }    }    else    if ( state == ESCAPE_STATE )    {        // if a valid escape sequence        if ( b == '[' )        {            state = PARAMS_STATE;        }        else // not an escape sequence        {             // allow escape to pass through            state = NORMAL_STATE;            processData( (byte) 27 );            processData( b );        }    }    else // NORMAL_STATE    {        if ( b == 27 )        {            state = ESCAPE_STATE;        }        else        {            processData( b );        }    }}

該方法實(shí)現(xiàn)了一個(gè)具有三個(gè)狀態(tài)的簡單狀態(tài)機(jī)。NORMAL_STATE 監(jiān)視任何 ESC 字節(jié)并將其他任何東西發(fā)送到 processData()。當(dāng)一個(gè) ESC 字節(jié)來到時(shí),ESCAPE_STATE 會(huì)接管并檢查下一個(gè)字節(jié)是否是 133 ([)。如果是,我們就轉(zhuǎn)到 PARAMS_STATE,同時(shí)累加參數(shù)字符串直到我們碰到此命令字符。我們在執(zhí)行該操作時(shí),調(diào)用 processCommand(),然后轉(zhuǎn)回 NORMAL_STATE

讀取命令參數(shù)的代碼值得進(jìn)行檢查。為了避免創(chuàng)建和保存 StringBuffer 所帶來的系統(tǒng)開銷,我們使用一個(gè)稱為 argbuf 的字符數(shù)組。為了避免不斷的內(nèi)存重新分配,我們使其比所需的大一些并保持富余,同時(shí)根據(jù)需要擴(kuò)大它。最后,為了跟蹤下一個(gè)字符到達(dá)何處,我們借用 Pascal 的一個(gè)技巧,將參數(shù)字符串的長度存儲(chǔ)在數(shù)組的第一個(gè)元素中。getArgument()getArgumentCount() 參數(shù)處理來自該數(shù)組的單個(gè)參數(shù)的分析和提取。

我們現(xiàn)在將曾經(jīng)位于 receive() 方法中的代碼轉(zhuǎn)到 processData() 方法。邏輯是一樣的,將進(jìn)入的字節(jié)放在當(dāng)前的光標(biāo)位置,除了接近方法主體末尾的這兩行外,代碼沒有變化:

/*** Appends the specified byte to the display buffer.*/protected void processData( byte b ){    ...    // increment bound if necessary    while ( cursor > bound ) bound += columns;        ...}


采用較早版本的 MIDTerm 的簡單的面向流的方法時(shí),光標(biāo)不僅標(biāo)出了進(jìn)入數(shù)據(jù)的插入點(diǎn),同時(shí)標(biāo)出了應(yīng)該在屏幕上顯示的數(shù)據(jù)緩沖區(qū)的外界。由于光標(biāo)現(xiàn)在可以向上和向前移動(dòng)到數(shù)據(jù)緩沖區(qū),就需要一個(gè)額外的變量來跟蹤數(shù)據(jù)的外界,以便我們可以確定屏幕的底部在什么位置。這個(gè)變量稱為 bound,必須跟蹤光標(biāo)并在光標(biāo)移動(dòng)時(shí)位于它前面。

雖然 processData() 處理了大部分字節(jié),但在接收到合法的終端命令時(shí)還是要調(diào)用 processCommand()。這個(gè)方法是我們的 ANSI 實(shí)現(xiàn)的核心。

/*** Executes the specified ANSI command, oBTaining arguments* as needed from the getArgument() and getArgumentCount() * methods.*/protected void processCommand( byte command ){    try     {        switch ( command )        {            ... // other commands go here            case 'd': // cursor to row x                 if ( argbuf[0] > 0 )                 {                    cursor = bound                      - ((rows-getArgument( 0 )+1)*columns)                      + ( cursor % columns );                }                break;                        case 'G': // cursor to column x                 if ( argbuf[0] > 0 )                 {                    cursor = cursor                      - ( cursor % columns )                      + getArgument( 0 );                }                break;                        ... // other commands go here                            default:                System.err.println( "unsupported command: "                     + (char) command                     + " : "                     + new String( argbuf, 1, argbuf[0] ) );                        }    }    catch ( Throwable t )     {        // probably parse exception or wrong number of args        System.err.println( "Error in processCommand: " );        t.printStackTrace();    }}

processCommand() 其實(shí)是一個(gè)大的 switch 語句,為所支持的每條命令都有一個(gè) case。不支持的命令進(jìn)入默認(rèn) case 并被忽略。這里所列出的兩個(gè) case 示范了處理命令的剩余部分的邏輯。

這里您可以了解操縱鼠標(biāo)所需的數(shù)組算法的種類了。記住,我們的二維屏幕是由一維字節(jié)數(shù)組來表示的,而且我們在內(nèi)存用盡之前將不會(huì)丟棄滾出屏幕頂端的數(shù)據(jù)。我們盡可能多地保留,以便用戶可以滾動(dòng)回來來查看他們可能漏看的任何內(nèi)容。由于這個(gè)原因,屏幕的原點(diǎn)必須相對于數(shù)組的末尾而不是開頭來計(jì)算,所以原點(diǎn)的位置在第 1 行、第 1 列。

如果我們不支持 scrollback 特性,要計(jì)算一對坐標(biāo)的數(shù)組下標(biāo)就很簡單:y * columns + x。要支持這一特性,我們就需要多做一些工作,并必須相對于我們的顯示緩沖區(qū)的外界來計(jì)算坐標(biāo)。如果這會(huì)使我們的用戶滿意,做這些額外的工作是值得的。

使其具備交互特性

為了使用戶更滿意而又不需要太多工作,可使他們能夠使用他們設(shè)備上的鍵盤來與遠(yuǎn)程主機(jī)交互。

我們較早的應(yīng)用程序與遠(yuǎn)程主機(jī)交互的方式,只能是通過執(zhí)行一組腳本形式的命令。用戶只能等待操作完成,然后使用箭頭鍵來滾動(dòng)數(shù)據(jù)緩沖區(qū)來查看返回的內(nèi)容。

在下一版本的 MIDTerm 中,我們將用戶的鍵擊信號直接發(fā)送到遠(yuǎn)程主機(jī)。要發(fā)送任何東西,我們都需要一個(gè)輸出流,所以 TelnetCanvas 現(xiàn)在有一個(gè) setOutputStream() 方法用于此目的。用戶輸入通過如下修改 keyPressed() 方法來處理:

...private byte[] move = new byte[] { 27, (byte) '[', 0 };...public void keyPressed( int keyCode ){    switch ( getGameAction( keyCode ) )    {        case LEFT:            // move cursor left one column            move[2] = 'D';            send( move );            break;        case RIGHT:            // move cursor right one column            move[2] = 'C';            send( move );            break;        case DOWN:            if ( isScrolling() )            {                // scroll down one row                scrollY++;                if ( scrollY > calcLastVisibleScreen() )                {                    scrollY = calcLastVisibleScreen();                }                repaint();            }            else             {                // move cursor down one row                move[2] = 'B';                send( move );            }            break;        case UP:            if ( isScrolling() )            {                // scroll up one row                scrollY--;                if ( scrollY < 0 ) scrollY = 0;                repaint();            }            else             {                // move cursor down one row                move[2] = 'A';                send( move );            }            break;        case FIRE:            // send a line feed:            send( (byte) '/n' );            break;        default:            // send code directly            send( (byte) keyCode );    }}


要注意的第一件事情是,在決定按哪個(gè)鍵之前我們要使用 getGameAction() 來將按鍵代碼轉(zhuǎn)換為游戲代碼。MIDP 設(shè)備的鍵盤布局不同:有些有箭頭按鍵和數(shù)字小鍵盤,有些只有數(shù)字小鍵盤可用作箭頭按鍵。getGameAction() 方法隱藏了這些復(fù)雜性。

如果所按的鍵是 UP、DOWN、LEFT 或 RIGHT,我們生成相應(yīng)的 ANSI 命令并將其發(fā)送到遠(yuǎn)程主機(jī)。注意 UPDOWN 有兩個(gè)模式:一個(gè)用于移動(dòng)光標(biāo),一個(gè)用于滾動(dòng)顯示內(nèi)容。當(dāng)前的滾動(dòng)模式由兩種新的方法 isScrolling()setScrolling() 來發(fā)現(xiàn)和控制。如果打開滾動(dòng),UPDOWN 將滾動(dòng)輸出而不是移動(dòng)光標(biāo)。注意,通過直接測試 scrolling 變量而不是調(diào)用 isScrolling() 來測試,我們可以節(jié)省一些系統(tǒng)開銷。

MIDP終端模擬之二:高級終端模擬(圖二)FIRE 鍵發(fā)送一個(gè)換行符,它類似于一般鍵盤上的 Enter 或 Return 鍵。這種特性對于基于菜單的應(yīng)用程序很有用,由箭頭鍵突出顯示一個(gè)選項(xiàng)并用 Enter 鍵選擇突出顯示的選項(xiàng);Lynx web 瀏覽器就是一個(gè)很好的例子。這些應(yīng)用程序僅使用用戶手持設(shè)備上的鍵盤就可以完全發(fā)揮作用。

如果按鍵代碼沒有映射到任何游戲動(dòng)作,就會(huì)將它直接發(fā)送到遠(yuǎn)程主機(jī)。MIDP 規(guī)范中規(guī)定,具有比標(biāo)準(zhǔn)手機(jī)的按鍵多的設(shè)備應(yīng)發(fā)送等同的 ASCII 字符作為其按鍵代碼。直接發(fā)送這些鍵代碼使得應(yīng)用程序可以完全利用具有完整鍵盤的設(shè)備的優(yōu)勢。具有這些設(shè)備的用戶只需開始輸入即可;他們的鍵擊會(huì)通過要建立的連接而發(fā)送。

最后,因?yàn)?TelnetCanvas 組件隱藏了來自應(yīng)用程序的其他部分的所有終端模擬邏輯,我們需要新的方法 getRows()getColumns()getTerminalType() 來宣布屏幕尺寸和實(shí)現(xiàn)所支持的終端模擬的種類。

更新 MIDlet

與以前一樣,MIDlet 類自身 MIDTermTelnetConnectionTelnetCanvas 捆綁在一起。只需要首位改變一下連接的設(shè)置:

...connection = new TelnetConnection(     (StreamConnection) Connector.open(         connectString, Connector.READ_WRITE, true ),    canvas.getColumns(),     canvas.getRows(),     canvas.getTerminalType() );input = connection.openInputStream();output = connection.openOutputStream();canvas.setOutputStream( output );...

但 MIDTerm 需要做更多。雖然 TelnetCanvas 處理基本用戶輸入,僅有數(shù)字鍵的鍵盤則需要特殊的方式來輸入文字,如重復(fù)按某個(gè)鍵來選擇某個(gè)字母,或預(yù)測式文字輸入法。利用這些內(nèi)在功能的唯一途徑就是使用 MIDP 的 TextFieldTextBox 組件。因?yàn)檫@些組件不能與 Canvas 位于相同的屏幕,文字輸入需要另外一個(gè)屏幕。雖然我們在屏幕上,但應(yīng)用程序還應(yīng)提供另一個(gè)屏幕來建立連接,這要用到主機(jī)名稱和要在其上連接的端口的字段。MIDTerm 將用作中心代理來將這些屏幕捆綁在一起。

Form 類非常靈活,所以我們不需要每個(gè)類都有一個(gè)單獨(dú)的子類,而這一點(diǎn)很讓人高興。大多數(shù) MIDP 設(shè)備用于應(yīng)用程序存儲(chǔ)的空間都有限,并限制應(yīng)用程序的大小,通常是最大 32 KB 或 64 KB,所以大小問題很重要。應(yīng)用程序中的每個(gè)類都會(huì)至少將 JAR  文件的大小增加半個(gè)千字節(jié),即使在模糊處理后仍是如此,所以應(yīng)盡可能地避免創(chuàng)建子類。

輸入窗體會(huì)經(jīng)常用到,所以將它創(chuàng)建在 MIDTerm 的構(gòu)造函數(shù)中,并在應(yīng)用程序運(yùn)行期間保持待用狀態(tài)。這種方法消除了創(chuàng)建輸入窗體帶來的任何可感知的延遲,并避免為窗體進(jìn)行重復(fù)內(nèi)存分配和垃圾收集而引起的內(nèi)存擾動(dòng)(memory churn)。輸入窗體的設(shè)置非常簡單:

...MIDP終端模擬之二:高級終端模擬(圖三)inputForm = new Form( "Input" );inputField = new TextField( null, "", 255, TextField.ANY );inputForm.append( inputField );inputOptions = new ChoiceGroup( null, Choice.MULTIPLE );inputOptions.append( INPUT_ENTER, null );inputOptions.append( INPUT_CTRL, null );inputOptions.append( INPUT_ESC, null );inputOptions.setSelectedIndex( 0, true ); // default trueinputForm.append( inputOptions );scrollOptions = new ChoiceGroup( null, Choice.MULTIPLE );scrollOptions.append( INPUT_SCROLL, null );inputForm.append( scrollOptions ); inputForm.addCommand( okCommand );inputForm.addCommand( cancelCommand );inputForm.setCommandListener( this );...


TelnetCanvas 會(huì)在用戶希望發(fā)送一些文字時(shí)激活該窗體。第一個(gè)字段是 TextField,而且在大部分平臺(tái)上它都應(yīng)獲得默認(rèn)焦點(diǎn)。稍微費(fèi)點(diǎn)功夫,用戶就可以快速調(diào)用該窗體,輸入一些文字,然后選擇 OK 命令來發(fā)送數(shù)據(jù)。

因?yàn)樵S多基于終端的應(yīng)用程序假定用戶應(yīng)采用終端類型的鍵盤,用戶就需要某種方法來發(fā)送特殊的鍵擊,如 Return、Escape 或 Control 加按鍵組合。我們?yōu)榇硕褂?ChoiceGroup,將其設(shè)置為 MULTIPLE 模式,以便我們得到復(fù)選框而不是互斥的單選按鈕。根據(jù)兩種復(fù)選框設(shè)置,用戶的文本將在 Escape 字符后發(fā)送,或在換行字符后發(fā)送。如果選擇了 Send as CTRL 選項(xiàng),發(fā)送每個(gè)字符時(shí)就像是按下了 Control 鍵一樣(Control 加按鍵代碼的計(jì)算方法,是將一個(gè)字符轉(zhuǎn)換為其大寫形式,然后從其值減 64)。Append ENTER 選項(xiàng)默認(rèn)為 true,因?yàn)榭捎眯詼y試表明大多數(shù)文字輸入后跟的是一個(gè)換行符。

最后,該窗體是允許客戶設(shè)置 TelnetCanvas 的滾動(dòng)模式的一個(gè)很好的地方。這一特性在功能上等同于終端鍵盤上的 Scroll Lock 鍵,而復(fù)選框也同樣地進(jìn)行標(biāo)記。為了進(jìn)行可視區(qū)分,這個(gè)選項(xiàng)加入一個(gè)單獨(dú)的 ChoiceGroup。

登錄窗體在一般的應(yīng)用程序生命周期內(nèi)很少會(huì)用到兩次以上,所以我們只根據(jù)需要來創(chuàng)建它,當(dāng)不用時(shí)就將其清除。其創(chuàng)建和布局在 onShowLogin() 中進(jìn)行:

MIDP終端模擬之二:高級終端模擬(圖四)public void onShowLogin(){    // create and populate login form    loginForm = new Form( "Connect to" );    hostField =         new TextField( "Host", host, 50, TextField.URL );    loginForm.append( hostField );    portField =         new TextField( "Port", port, 6, TextField.NUMERIC );    loginForm.append( portField );    loginForm.addCommand( exitCommand );    loginForm.addCommand( openCommand );    loginForm.setCommandListener( this );        // show form    display.setCurrent( loginForm );}

雖然這是一個(gè)簡單的窗體,可用性仍是我們最重要的考慮。一些實(shí)現(xiàn)可以利用一個(gè) TextFieldURLNUMERIC)上的“線索”并適當(dāng)?shù)囟ㄖ朴脩艚缑妗R驗(yàn)橛脩敉ǔ⒃?B> Host 中輸入服務(wù)器的域名,指出所期望的用戶輸入像一個(gè) URL 就很有意義。某些設(shè)備可能有特殊的屏幕布局,它們針對字母和符號而不是數(shù)字進(jìn)行優(yōu)化。同樣地,Port 字段應(yīng)僅限于數(shù)字輸入;一些設(shè)備可能允許用戶在它們的鍵盤上快速輸入數(shù)字,而繞過任何重復(fù)按鍵式文字輸入系統(tǒng)。

MIDlet 是登錄窗體、輸入窗以及 Telnet canvas 的命令監(jiān)聽器。可將其視作應(yīng)用程序工作流的向?qū)А?nbsp;   MIDP終端模擬之二:高級終端模擬(圖五)MIDP終端模擬之二:高級終端模擬(圖六)MIDP終端模擬之二:高級終端模擬(圖七)MIDP終端模擬之二:高級終端模擬(圖八)MIDP終端模擬之二:高級終端模擬(圖九)

在啟動(dòng)時(shí),將出現(xiàn)登錄窗體,選項(xiàng)為 OpenExit。 一旦打開,就會(huì)出現(xiàn) Telnet canvas,選項(xiàng)為 CloseInputInput 選項(xiàng)顯示輸入窗體,其中有一個(gè) OK 選項(xiàng)用于隱藏窗體并發(fā)送文字,另有一個(gè) Cancel 選項(xiàng)僅僅隱藏窗體。Close 選項(xiàng)隱藏 Telnet canvas 并顯示一個(gè)登錄窗體。最后,Exit 選項(xiàng)調(diào)用 notifyDestroyed() 并退出應(yīng)用程序。所有這些命令由 MIDTermcommandAction() 方法來處理。

讓我們使它工作起來

現(xiàn)在所有組件已經(jīng)就緒,我們就可以使我們的終端模擬器工作起來了。終端應(yīng)用程序在企業(yè)和教育計(jì)算環(huán)境中得到廣泛應(yīng)用,用于企業(yè)應(yīng)用程序、軟件開發(fā)、系統(tǒng)管理甚至對策模擬。MIDTerm 使得所有這些種類的應(yīng)用程序和資源都可以從您的移動(dòng)設(shè)備來訪問。


軟件開發(fā): emacs
MIDP終端模擬之二:高級終端模擬(圖十)
系統(tǒng)管理: top
MIDP終端模擬之二:高級終端模擬(圖十)
Gaming: starcross
MIDP終端模擬之二:高級終端模擬(圖十二)

更進(jìn)一步,任何這些應(yīng)用程序都可以被“刮擦”:您可以編寫一個(gè)移動(dòng)應(yīng)用程序來與遠(yuǎn)程服務(wù)器上的資源密集型程序進(jìn)行交互、提取輸出并將它呈現(xiàn)在一個(gè)用戶友好的圖形界面上。企業(yè)開發(fā)者通常使用這種技術(shù)來在遺留系統(tǒng)上構(gòu)造新式的用戶界面。

MIDP 平臺(tái)上的有效 Telnet 和 ANSI 終端實(shí)現(xiàn)清除了這些種類的軟件項(xiàng)目的主要障礙。

結(jié)束語

通過實(shí)現(xiàn)對 ANSI 的終端轉(zhuǎn)義序列的支持,我們已經(jīng)更新了第一篇文章的未完善的終端顯示。這個(gè)應(yīng)用程序還更好地利用了 MIDP 的用戶界面功能,并具有對用于用戶輸入的鍵盤和定制窗體的支持。您可以組合和匹配這些軟件組建來為新的種類的網(wǎng)絡(luò)意識(network-aware)移動(dòng)應(yīng)用程序提供基礎(chǔ)。

有關(guān)詳細(xì)信息

(出處:http://www.companysz.com)



發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 一区二区三区日韩在线 | 欧美日韩夜夜 | 久久国产精品久久久久久久久久 | 男男羞羞视频网站国产 | 中文字幕在线网 | 一起草av在线 | 又黄又爽免费无遮挡在线观看 | 一区二区三区在线观看免费视频 | 欧美日本免费一区二区三区 | 国产91精品一区二区麻豆亚洲 | 日韩精品中文字幕一区二区三区 | 美女黄网站免费观看 | 91精品国产91久久久 | 久久蜜臀一区二区三区av | 久久综合九色综合久久久精品综合 | 一本色道久久综合亚洲精品小说 | 国产免费资源 | 草逼一区| 视频一区二区三区在线播放 | 特色一级黄色片 | 综合网天天色 | 日本一区二区视频在线观看 | 日韩欧美视频一区二区三区 | 成年人网站视频免费 | 国产一区二区在线观看视频 | 亚洲视屏在线 | 嫩草影院在线观看网站成人 | 久久国产精品久久久久久久久久 | 日本黄色免费片 | 久久成人免费网站 | 午夜生活理论片 | 午夜精品老牛av一区二区三区 | 亚洲精品在线观看网站 | av噜噜在线 | 国产一区二区三区在线免费观看 | 亚洲第一页综合 | 成人毛片网站 | 国产又粗又爽又深的免费视频 | 国产成人高潮免费观看精品 | 久久精品日韩一区 | 日本精品久久久久 |