犀角(Diceros Horn) 2006 01 09

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

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

Mon, 09 Jan 2006

ルービックキューブ

以前作ったルービックキューブのシミュレーションプログラムを Java Web Start で起動できるようにしてみました。ただし、セキュリティ証明書は 証明書発行期間から取得したわけではない、いわゆるオレオレ証明書。 しかも6ヶ月で期限切れになる。対策はそのうち考えます。

画面下のボタンを押すか、色名のキーを押すと、 その色が中心にある面をその面の上から見て 時計回りに90度回転します。

posted at 23:23 | category: /Program | 固定リンク(ルービックキューブ )

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 )

Java3D リンク集

Java 3D(TM) API Home Page
Sun による本家ホームページ。API の仕様書も読める。
Java 3D for Linux: Status and Information
Linux 用の Java3D の開発元 Blackdown
Java Friendly Society
「Java3Dプログラミング・バイブル」についての情報など。
Atsushi's Homepage 〜 Java3DTips
Atsushi さんによる Tips。大変役に立つページです。
Java 3D API Collateral
SUN が出している公式のAPI解説書。これを熟読すれば、他の解説書は要らな いかもしれません。
The Java 3D Community
総合的なサイトとしてはまずここがお勧め。ただし英語。困ったときは まずここの FAQ にあたると解決することも。
Java 3D Programming
英語の本です。ebook Edition をダウンロードすることができます。 API の仕様について細かく解説している本。一通りプログラムの作り方が わかった後に、自分の実現したいことを調べるのに役にたつ。
Java 3D
ABA さんのペ−ジ。Java3D で作ったゲ−ムなどがある。
vecmath package
Kenji Hiranabe さんの unofficial Java3D vecmath package。 「vecmath を理解するための数学」は必読。
Archives of JAVA3D-INTEREST@JAVA.SUN.COM
java3d-interest メーリングリストの過去記事が読めます。

posted at 13:55 | category: /Java/Java3D | 固定リンク(Java3D リンク集 )