犀角(Diceros Horn)

とくながの「書き散らかし」です

ここは研究・調査・開発などの記録がメインのページです。 日常の雑事、読書記録は はてなダイアリー の方に書いています。よろしければそちらもどうぞ。

Sun, 12 Feb 2006

jar の使い方

jar でクラスファイルを固めるには

ほぼ tar コマンドと同じように使えばよい。

$ jar cvf jarfile classfiles

jar で固めたファイルをアプレットタグに使うには

<APPLET  CODE="MainApplet" ARCHIVE="hogehoge.jar" WIDTH="800" HEIGHT="500" >
のように ARCHIVE パラメータを設定する。

jar で固めたファイルを実行するには

まず、jar で固めるときに manifest ファイルを指定して どのクラスの main メソッドを実行するかを指定する。 例えば MainClass と言う名前のクラスの main メソッドを実行する場合は manifest ファイルは次のように書く。
Manifest-Version: 1.0
Created-By: 1.3.1 (Sun Microsystems Inc.)
Main-Class: MainClass
これを適当な名前で保存して、jar で固めるときに次のように
$ jar cvfm jarfile manifestfile classfiles
このファイルを指定する。

実行するときには、java コマンドの -jar オプションをつければよい。

$ java -jar jarfile

このときはクラス名をつける必要はない。クラス名は jar ファイルの中の manifest ファイルの情報から自動的に取り出される。

posted at 22:07 | category: /Java/tips | 固定リンク(jar の使い方)

Mon, 09 Jan 2006

Canvas の内容を jpeg ファイルに保存するには

Canvas の内容をそのまま保存することはできない。 BufferedImage に書き込んで、Canvas には drawImage() で書き込むことにしておく。 その状態で、image を BufferedImage のインスタンスとして、

    FileOutputStream output = new FileOutputStream("test.jpg");
    JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(output);
    jpeg.encode(image);
    output.flush();
    output.close();
とすればよい。ただし、IOException を throw するので例外処理が必要。

サンプルソース 参照。

posted at 19:38 | category: /Java/tips | 固定リンク(Canvas の内容を jpeg ファイルに保存するには )

ダブルバッファリング

Canvas に図形を描画するときに、直接 Graphics に書き込むのではなく、 バッファーとして Image オブジェクトを作成し、その Graphics に書き込んでから drawImage メソッドで Canvas の Graphics に書き込む。

具体的には、Canvas のフィールド変数として、

    Image image;            // イメージの保存
    Graphics g0;            // image に描画するための Graohics
を追加し、paint() メソッドは
    public void paint(Graphics g){
        // image が初期化されていたいときは初期化する
        if(image == null){
            image = createImage(getSize().width,
                                getSize().height);
            // Graphics の取得
            g0 = image.getGraphics();
        }
        // image を表示する
        g.drawImage(image,0,0,this);   
    }
とし、実際の描画は
        g0.fillRect(20,20,50,50);
        getGraphics().drawImage(image,0,0,this);
のように g0 に書き込んでから drawImage で Canvas に書き込めばよい。

posted at 19:36 | category: /Java/tips | 固定リンク(ダブルバッファリング )

アプレットとアプリケーションの兼用プログラム

アプレットを作るときに、わざわざhtmlファイルを書いてブラウザで 動作を確認するのは面倒である。(appletviewer をつけばちょっと楽だが) そんなときはアプレットとして作ったプログラムをアプリケーションとして実行 させよう。

次のアプレットはボタンを押せばメッセージが出ると言う定番のアプレットだが、 これをアプリケーションとして動くようにするために、main メソッドを付け足 している。そこでは、Frame を生成し、Applet を張り付けているだけである。

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class HelloAppletcation extends Applet{
  Button bt;
  TextField tf;
  
  public static void main(String args[]){
    Frame fr = new Frame("Hello Applet");
    fr.addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
	System.exit(0);
      }
    });
    Applet app = new HelloAppletcation();
    app.init();
    fr.add(app);
    fr.setSize(400,100);
    fr.setVisible(true);
    app.start();
  }

  public void init(){
    bt = new Button("PUSH");
    tf = new TextField(30);
    add(bt);
    add(tf);
    bt.addActionListener(new HelloButton());
  }

  class HelloButton implements ActionListener{
    public void actionPerformed(ActionEvent e){
      tf.setText("Hello, Java World!!");
    }
  }
}

動的に Applet として実行しているか Application として実行しているかを 判定したい場合は、Applet クラスの getCodeBase() メソッドを呼ぶとよい。 Application の場合は例外が発生する。

posted at 19:35 | category: /Java/tips | 固定リンク(アプレットとアプリケーションの兼用プログラム )

クラスの動的読み込み

実行時にクラスを呼ぶ例を挙げよう。 まず A(String str,double x) と言うコンストラクタを持つようなクラス A を考えよう。このクラス A を動的に呼んでインスタンス化するには次のようにする。 ここで、ClassLoader クラスは抽象クラスなので、それを継承したクラスを ClassLoadTest とする。

  ClassLoader loader = new ClassLoadTest();
  Class c = loader.loadClass("A");
  Constructor con = c.getDeclaredConstructor(
                    new Class[]{String.class,double.class});
  A a = (A)con.newInstance(new Object[]{"circle",new Double(3.14)});
例外処理に付いては省略した。

posted at 19:33 | category: /Java/tips | 固定リンク(クラスの動的読み込み )

内部クラスから外のクラスを呼ぶ

外のクラス名.this でアクセスできる。

class InnerOuter{
    String str = "Outer";
    A a;
    InnerOuter(){
        a = new A();
    }

    class A{
        String str = "Inner";
        
        void outerMessage(){
            System.out.println(InnerOuter.this.str);
        }

        void innerMessage(){
            System.out.println(this.str);
        }
    }

    public static void main(String args[]){
        InnerOuter inn = new InnerOuter();
        inn.a.outerMessage();
        inn.a.innerMessage();
    }
}
これをコンパイルして実行すると、
$ java InnerOuter
Outer
Inner
のように出力される。

posted at 19:29 | category: /Java/tips | 固定リンク(内部クラスから外のクラスを呼ぶ )

あるオブジェクトがあるクラスのオブジェクトかどうかを判定する

この手の実行時型判定は instanceof または Class クラスの isInstance() メソッドまたは Class クラスの isAssignableFrom() メソッドを使う。 次の3つは全て同じ意味で、オブジェクト a がクラス A またはそのサブクラスの インスタンスのときに true を返す。

  • a instanceof A
  • A.class.isInstance(a)
  • A.class.isAssignableFrom(a.getClass())
また、次のように書くと、オブジェクト a がクラス A またはその スーパークラスのインスタンスかどうかを判定できる。
  • a.getClass().isAssignableFrom(A.class)
詳しくは Class クラスのAPI仕様書を参考のこと。

posted at 19:28 | category: /Java/tips | 固定リンク(あるオブジェクトがあるクラスのオブジェクトかどうかを判定する )

RMIの例

RMI の例として、クライアント側の名前を登録、解除、および 現在登録されている名前全てを得る RMI サーバを作成。 チャットなどに応用できるだろう。

$ javac MyRemote.java
$ javac MyServer.java
$ javac MyClient.java
$ rmi MyServer

とした後に、

$ java MyServer

と実行し、 同じホスト上で、

$ java MyClient

とすると、

server> John Lennon
-------------------------
server> John Lennon
server> Paul McCartney
server> George Harrison
server> Ringo Starr
-------------------------
server> Paul McCartney
server> Ringo Starr
-------------------------

のように表示されるはず。

posted at 19:03 | category: /Java/tips | 固定リンク(RMIの例 )

ThreadのOn/Off

Thread の制御には wait() と notify() が用意されているが、 多くのサンプルでは Thread を起動するたびにインスタンス化して、不要になったら null を代入することで実現している。それでできてしまうのだから問題ないと言う 考え方もあるだろうが、ここでは wait() notify() を使う方法を考えてみよう。

基本

  • wait() でスレッドを待機状態にする
  • notify() でスレッドを再開する
  • wait() と notify() は synchronized させる

同じスレッドの wait() と notify() を実行することと、実行するときに syncronized(スレッドのオブジェクト)で同期させる。 以下にアプレットでスレッドを使うときの例を挙げる。

/*
<applet code="AppletOnOff" width="100" height="100">
</applet>
 */
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class AppletOnOff extends Applet{
    TextField tf;
    long n = 0;
    SuspendableThread th;
    Button btn;

    public void init(){
	add(btn = new Button("START"));
	add(tf = new TextField(Long.toString(n),10));
	btn.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent evt){
		    if(btn.getLabel().equals("START")){
			th.restartThread();
			btn.setLabel("STOP");
		    }else{
			th.suspendThread();
			btn.setLabel("START");
		    }
		}
	    });
	th = new SuspendableThread();
	th.start();
    }

    class SuspendableThread extends Thread{
	boolean flag = false;

	public void suspendThread(){
	    flag = false;
	}
	
	public void restartThread(){
	    flag = true;
	    synchronized(this){
		notify();
	    }
	}
	
	public void run(){
	    while(true){
		try{
		    th.sleep(100);
		    if(!flag){
			synchronized(this){
			    wait();
			}
		    }
		}catch(InterruptedException e){
		}
		n++;
		tf.setText(Long.toString(n));
	    }
	}
    }
}

posted at 18:48 | category: /Java/tips | 固定リンク(ThreadのOn/Off )