アプレットを簡単な方法でテストします。アプレットをアプリケーションに変換します。

OKあなたは、Hello Worldアプレットを過ぎて、はるかに大きく、はるかに興味深いものに進んでいます。まだブラウザベースのインターフェイスが必要なので、プログラムをアプレットとして開発します。しかしprintln、Netscapeにsを挿入してアプレットをデバッグするのは簡単ではなく、appletviewerはもう正しく機能していないようです。それとも両方のアプレットとして有用であろうプログラム書いている、スタンドアロンアプリケーションとしての。あなたは可能性が差し込むmain、あなたの中の関数をApplet、サブクラス、およびブラウザのがいることを、今、ハンドルのコマンドライン引数、ウィンドウ操作、および画像の読み込み、自分自身にコードを追加しAppletContext、もはやそこにあなたのためではありません。

AppletContextはインターフェイスであるため、AppletContextオブジェクトをインスタンス化して、ブラウザがAppletContext通常提供する機能を提供することもできません。ただし、インターフェイスを実装することはできます。また、非常に一般的な方法で実装した場合は、独自のツールチェストに入れて何度も再利用できます。この記事では、その方法を説明します。実際、この記事の最後にソースコードが含まれているため、自分で実装を作成する必要はありません。

クラスとインターフェース

ブラウザベースの環境を複製するという目標を達成するには、実際にはいくつかのインターフェイスを実装する必要がAppletContextありAppletStubます。特に、および。AppletContextアプレットの環境を表すことになっています。通常はブラウザであり、HTMLドキュメントを囲んでいます。AppletStubで使用されているApplet、あなたがこのようなを呼び出すことができ、アプレットの機能を実装してヘルプをスーパークラスgetAppletContext()getParameter()。もう1つのインターフェースも実装しますURLStreamHandlerFactory。これについては後で説明します。

これまではインターフェースのみを実装しているため、何かを拡張するオプションがあります。ブラウザはアプレットが描画されるウィンドウを提供するため、Frameオブジェクトが必要です。DummyAppletContext拡張するクラスを作成しましたFrame; その定義は始まります:

パブリッククラスDummyAppletContextはFrameを拡張し、AppletStub、AppletContext、URLStreamHandlerFactoryを実装します{ 

初期化

DummyAppletContext;をインスタンス化する方法はいくつかあります。最も便利なものの1つは、クラス自体のmain関数(以下に示す)から直接DummyAppletContext取得することです。このように、スタンドアロンアプリケーションとして実行するためだけにアプレットを定義する必要はありませんmain。を介して、アプレットをそのまま実行できるようになりますDummyAppletContext

public static void main(String args []){new DummyAppletContext(args); }

上記の新しい演算子は、引数リストを受け取るコンストラクターを呼び出します。最初の引数はAppletサブクラスの名前であると想定し、クラスをインスタンス化しようとします。Class静的関数を使用しforName()Classオブジェクトを取得し、そのnewInstance()関数を呼び出してアプレットをインスタンス化します。この1行から多数の例外を取得できますが、それらはすべて回復不能です。したがって、例外が発生した場合は、単に印刷して終了します。それが機能する場合は、すべてのコンストラクターで使用するプライベート初期化関数を呼び出します。コンストラクターのコードは次のとおりです。

public DummyAppletContext(String args []){

スーパー(args [0]);

{アプレットapplet =(Applet)Class.forName(args [0])。newInstance();を試してください。

init(アプレット、640、480、args、1); } catch(Exception e){e.printStackTrace(); System.exit(1); }}

他のコンストラクターの1つ(以下に表示)は、既存のアプレットオブジェクトを取ります。このコンストラクターmainは、Appletサブクラス自体など、別のクラスに関数を実装する場合に使用します。実際、これは単なる便宜です。ではmain関数Appletサブクラス、私は上のJavaインタプリタを実行して、プログラムを起動することができApplet、サブクラスではなく、上でそれを実行したDummyAppletContextと指定しApplet、別途(サブクラスをjava MyAppletjava DummyAppletContext MyApplet)。また、アプレットのデフォルトの幅と高さを指定することもできます。(私はこのようなコンストラクターをもう1つ提供しますが、これはデフォルトの幅と高さの引数を必要としません。)

public DummyAppletContext(アプレットapplet、int default_width、int default_height、String args []){

スーパー(applet.getClass()。getName());

init(アプレット、default_width、default_height、args、0); }

このinit関数は、セットアップの魔法のほとんどを実行します。その引数には、アプレットオブジェクト、デフォルトサイズ、コマンドライン引数、および引数の開始インデックスが含まれます。コンストラクターの1つで最初の引数を使用して、Appletロードするサブクラスをその名前のみで決定したことを思い出してください。その場合、(startidxアプレットの引数とパラメータの解析を開始するインデックス)は1ですが、それ以外の場合は0です。init関数は最初にURL、このオブジェクトがデフォルトになることをクラスに通知しますURLStreamHandlerFactory。 (このためのインターフェースを実装しています。)次に、指定されたアプレットを、この1つのアプレットのみを含むアプレットのベクトルに追加し、このオブジェクトがそのとして機能することをアプレットに通知しますAppletStub。ここにあるinit関数は:

private void init(アプレットapplet、int default_width、int default_height、String args []、int startidx){

URL.setURLStreamHandlerFactory(this);

applets.addElement(アプレット); applet.setStub(this);

initial_width = default_width; initial_height = default_height;

parseArgs(args、startidx);

status = new TextField(); status.setEditable(false);

add( "Center"、applet); add( "South"、status);

applet.init(); appletResize(initial_width、initial_height);

公演(); applet.start(); }

引数は、配列要素をループし、引数のすべてのペアを名前と値のペアのハッシュテーブルに追加するだけで解析されます。引数は-width-heightは特別に扱われ、およびアプレットのデフォルトの幅と高さをオーバーライドします。それらはハッシュテーブルに追加されません。引数の解析は、次にparseArgs示す関数で行われます。

public void parseArgs(String args []、int startidx){for(int idx = startidx; idx <(args.length --startidx); idx + = 2){try {if(args [idx] .equals( "-width" )){initial_width = Integer.parseInt(args [idx + 1]); } else if(args [idx] .equals( "-height")){initial_height = Integer.parseInt(args [idx + 1]); } else {params.put(args [idx]、args [idx + 1]); }} catch(NumberFormatException nfe){System.err.println( "警告:コマンドライン引数" + args [idx] + "は有効な数値ではありません。"); }}}

このinit関数はshowStatus、編集不可能なAWTテキストオブジェクトを使用して(関数によって使用される)ステータス領域を設定することによって続行します。DummyAppletContextデフォルトのBorderLayoutポリシーに従って、アプレットとステータス領域のコンポーネントをフレーム()に追加し、アプレットのinit関数を呼び出し、指定されたとおりにウィンドウのサイズを変更します。最後に、ウィンドウが表示され、アプレットinitstart関数が呼び出されます。 (私たちは、呼び出す必要があります決してstop、そしてstartまた、私は使ったことがない私たちは、ブラウザでじゃないので、再び呼び出されることはありません。destroy私はそれを呼び出すことはありませんので、何のための方法を。しかし、あなたはそれを必要としている場合は、IすべてのSystem.exit()呼び出しの前に呼び出すことをお勧めしますinit()。最初に、呼び出されたかどうかをテストします。)

handleEvent()以下に示すように、1つのFrame関数をオーバーライドするだけでよいので、ユーザーがウィンドウバーの閉じるアイコンを押した場合にWINDOW_DESTROYイベントをキャッチできます。

public boolean handleEvent(Event evt){

if(evt.id == Event.WINDOW_DESTROY){System.exit(0); }

super.handleEvent(evt);を返します。}

AppletStub

AppletStub

実装する必要のあるいくつかの関数を宣言します。

  • isActive -常にtrueを返します

  • getDocumentBase -現在のディレクトリの「ファイル」URLを返します

  • getCodeBase-を返すのと同じものをgetDocumentBase返します

  • getParameter-組み込みのハッシュテーブルにインデックスを付け、parseArgs一致する値を返すか、存在しない場合はnullを返します

  • getAppletContext-「this」オブジェクトを返します(our DummyAppletContext

  • appletResize -アプレットのサイズを変更する要求に対応するために、ウィンドウのサイズを変更しようとします

Most of these functions are pretty straightforward. However, I did have to do some special things to make getDocumentBase to work the way I wanted it to. I started by creating a reference to a dummy file. Using an object of the File class, I called getAbsolutePath() to get the full path name of the file. For DOS (Windows), I had a file name with a bunch of backslashes in it. My objective was to create a URL, so I had to replace these slashes with forward slashes. Also, the typical browser expects the colon (:) in a DOS filename to be replaced with a vertical bar (|) in the URL. The code below performs a transformation of the dummy file to what appears to be a Netscape-compliant URL.

 public URL getDocumentBase() { URL url = null; try { File dummy = new File( "dummy.html" ); String path = dummy.getAbsolutePath(); if ( ! File.separator.equals( "/" ) ) { StringBuffer buffer = new StringBuffer(); if ( path.charAt(0) != File.separator.charAt(0) ) { buffer.append( "/" ); } StringTokenizer st = new StringTokenizer( path, File.separator ); while ( st.hasMoreTokens() ) { buffer.append( st.nextToken() + "/" ); } if ( File.separator.equals( "\\" ) && ( buffer.charAt(2) == ':' ) ) ' );  else { } path = buffer.toString(); path = path.substring( 0, path.length()-1 ); } url = new URL( "file", "", -1, path ); } catch ( MalformedURLException mue ) { mue.printStackTrace(); } return url; } 

The only other AppletStub function implementation of note is appletResize(). In this function, I not only found that I needed to take into account the size of the status text box, but I also had to accomodate the window decorations (for example, the title bar). Java provides the function needed to get that information in Frame's insets() function. Here is the appletResize function:

public void appletResize( int width, int height ) {

Insets insets = insets();

resize( ( width + insets.left + insets.right ), ( height + status.preferredSize().height + insets.top + insets.bottom ) ); }

AppletContext

The functions required to implement

AppletContext

include:

  • getAudioClip -- returns null, because there doesn't seem to be a toolkit for audio clips in my JDK. (You could handle this differently, returning your own implementation of AudioClip.)

  • getImage -- gets an image from the given URL. For the purposes of the DummyAppletContext, all URLs are assumed to be references to a local file. Therefore getImage converts the URL to a file name, and uses the AWT Toolkit object to load the image.

  • getApplet -- is supposed to return an applet by name. I never name my applet, and there are no other applets, so this always returns null.

  • getApplets -- returns an Enumeration of the applets in this AppletContext. There is only one, so this returns an Enumeration of one element. The Enumeration is created from the Vector we filled in the init function.

  • showDocument -- There are two variations of this function, neither one of which actually shows a document. In a browser, showDocument requests that a document at the given URL be loaded. I actually do show this request in the status area, but I don't attempt to retrieve or show the document.

  • showStatus -- writes the given text to the Text object used as the status area.

The getImage() function uses a private function filenameFromURL() to convert the URL back to a legal file name for the current operating system. Again, I have to make special provisions for DOS, taking into account variations I have seen from time to time. In particular, I have to convert the URL's vertical bar back to a colon.

private String filenameFromURL(URL url){String filename = url.getFile(); if(filename.charAt(1)== '|'){StringBuffer buf = new StringBuffer(filename); buf.setCharAt(1、 ':'); ファイル名= buf.toString(); } else if(filename.charAt(2)== '|'){StringBuffer buf = new StringBuffer(filename); buf.setCharAt(2、 ':'); ファイル名= buf.toString(); }ファイル名を返す; }

URLStreamHandlerFactory

URLStreamHandlerFactory

機能は1つだけです。

createURLStreamHandler()

。私はこの関数を実装して、

URLStreamHandler

アプレットがURLへの接続を開こうとするたびに使用されます。今、私が電話すると

openStream()

私のJavaアプリケーションのURLでは、実際には入力用にローカルファイルへのストリームを開きます。ここは

createURLStreamHandler()