Lecture

Java プログラミング入門

このページは、学部2年生向け授業である、「マルチメディアプログラミング実習」 のために用意しました。

javaのマニュアル

http://docs.oracle.com/javase/jp/8/docs/api/index.html

出来上がったプログラムの提出方法

  • フォルダを作ってその中にjavaファイルとclassファイル を入れてください。 フォルダの中のclassファイルをダブルクリックしたらプログラムが起動することを確認してください。
  • このフォルダに名前を付けてください。フォルダの名前は、「出席番号+氏名(ローマ字の姓名)+必要ならばバージョン番号の数字」にしてください。たとえば09020999siioitiro01のように。なお全部半角英数字でお願いします。
  • このフォルダを圧縮してください
    • フォルダを選択してファイルメニューから圧縮を選択します
  • 圧縮したファイルを以下の手順で
    /home/isstaff/siio/Public/Drop Box/.
    に提出してください。ターミナル.appからなら
    cp 123456siioitiro.zip /home/isstaff/siio/Public/Drop\ Box
    としてください。ファインダーからなら、メニューから「移動」「フォルダへ移動...」を選んで 以下のように入力して、移動ボタンを押して、そこに現れるドロップボックスホルダに、ドラッグアンドドロップしてください。

http://siio.jp/gyazo/dropbox.png

  • 書き込み専用なので確認できないけどokですかという意味のダイアログが出るかと思いますが問題ありません。
  • レポート提出用フォルダは書き込み専用で見ることができません。アップロードできたかどうか不安でしたら教員まで質問してください。
  • 授業中でしたら、ココを見ると一覧をみることができます。
  • 同じ名前のフォルダを投げ込むと、エラーになります。ということで新しいバージョンができたら別の名前のフォルダを作って提出し直してください。(フォルダ名最後に数字をつけてください)

教科書

http://gyazo.com/de3288074dae1c75f6df4ef3c0b9b3d4.png

http://www.amazon.co.jp/dp/4883732258/

買ってください。もしくは、先輩から安く譲ってもらってください。

この講義の目的

  1. Javaでプログラムする
  2. オブジェクト指向の概念を理解してプログラミングする
  3. GUIプログラミングをする

この講義の順序

  1. Javaになれる(C言語などのプログラミング手法の復習)
  2. オブジェクト指向について理解する
  3. GUIプログラミングについて理解する(イベント駆動)
  4. お絵描きプログラムを作ってみる

成績評価

  1. お絵描きプログラムの完成度,作り込み
  2. 毎回の宿題の達成(参考程度)
  3. 出席状況(参考程度)

第1章および第2章

terminalを起動する

http://siio.jp/gyazo/7366bfab668207c6598c4d88ef70d2d4.png

  • terminalは、/Applications/Utilities/の中にあります。 ちなみに、/Applicationsはファインダでは/アプリケーションと日本語として見えます。 /Applications/Utilities/は、/アプリケーション/ユーティリティ/と日本語として見えています。
  • ダブルクリックすると起動します。 よく使うことになると思いますので、dockにドラッグアンドドロップして 登録しておくと良いかと思います。
  • ターミナルから、javacとタイプしてみてください。Javaがすでに入っているので、 オプションの説明が日本語で出てくると思います。

おすすめテキストエディタCotEditor?

https://coteditor.com/img/appicon/128@2x.png

  • Javaのプログラムを作るテキストエディタです。一番簡単にはterminalからviとかemacsとかpicoとかタイプして エディタを呼び出せば良いです。
  • でも日本語の設定などが結構難しいので、GUIベースのエディタを使ってみましょう。
  • いくつかありますが、おすすめの一つはCotEditor?という、便利なフリーウェアのテキストエディタです。
  • これも便利なのでdockに入れておくとよいと思います。

こちらからダウンロードできます。 演習室のOSにあわせたバージョンをダウンロードして~/Applicationsにコピーします。

https://coteditor.com/archives.ja

超簡単なプログラム(hello world)を作ってみる

  • ターミナルから、vi Hello.javaとかemacs Hello.javaとかpico Hello.javaとかタイプしたり、 もしくは、cotEditerを起動して作成します。
  • ここで、以下のようなプログラムを書いてみます。
class Hello {  
public static void main (String args[]) {
        System.out.println("hello java world!");
        }
}

http://siio.jp/gyazo/20121004010107.png

  • これをHello.javaという名前で保存して、コンパイル実行します。すると以下のようになります。
javac Hello.java  (コンパイルする)
java Hello      (実行する。.javaなどの拡張子は不要)
hello java world!   (結果)
  • 次に簡単なウィンドウを出してみましょう。

授業の最後の方で紹介する,Swingというフレームワークを使ってウィンドウを出してみます.

import javax.swing.JFrame;
public class SimpleWindow {

       public static void main(String argv[]) {
               JFrame f = new JFrame("私が作った最初の窓");
               f.setSize(200,100); 
               f.setVisible(true);
       }

}

これをSimpleWindow.javaという名前で保存して、

javac SimpleWindow.java
java SimpleWindow

とタイプしてコンパイル/実行します。 このプログラムは,ウィンドウのクローズボタンを押しても終了しません. プログラムを停止するには,ターミナルでコントロール-cを押します.

simplewindow.png

第3章

  • 演習1
  • 演習3.4をみて、自分の名前の最初の文字の文字コードを表示してみてください。
  • 演習2
  • コマンドの引数はarg[0], arg[1] ... などにString型の配列としてプログラムに引き渡されます。
  • 二つの引数を与えたときに、それが+でつないで表示されるプログラムを作りましょう。

http://gyazo.com/8159f78165e17781a7110de3763c833c.png

ヒント

  • 以下は引数一つを表示するだけのサンプルです。これをもとに考えてください。
  • arg[0]とarg[1]をprintlnの中で+でつないで表示すれば良いです。
class ArgsTest {  
public static void main (String args[]) {
	System.out.println(args[0]);
        }
}

解答

  • 後で公開します
class ArgsTest {  
public static void main (String args[]) {
	System.out.println(args[0] + " + " + args[1]);
        }
}

第4章

  • 演習4.2をやってみよう

第5章

演習

  • 演習問題5.4(変更)

乱数を10個表示する

public class Score {
	public static void main (String argv[]) {
		int i,a;
		for(i=0;i<10;i++) {
			a=(int)(Math.random() * 100);
			System.out.println(a);
		}
	}
}

次にこの乱数を点数とみなして、演習問題5.4の基準に従ってABCDを表示するプログラムを書け。 動作例を以下に示す。

http://gyazo.com/829b04a7fc82cdfe9dd0dfa650af873e.png

解答例:

public class Score {
	public static void main (String argv[]) {
		int i,a;
		for(i=0;i<10;i++) {
			a=(int)(Math.random() * 100);
			System.out.print(a + " ");
			if(a<40) System.out.println("D");
			else if(a<60) System.out.println("C");
			else if(a<80) System.out.println("B");
			else System.out.println("A");
		}
	}
}
  • 演習問題5.5をやってみよう

http://gyazo.com/1733defca0c709c41c69ea729320ab61.png

解答例:

class Kinri {
public static void main (String args[]) {
	double okane=100000;
	int year;
	year=1;
	while(okane < 200000) {
		okane = okane * 1.05;
		System.out.println("year = " + year + "  okane= " + okane);
	 	year++;
	}
}
}

現在の普通預金の金利0.04%だと倍になるのに何年かかるだろうか。確かめてみよう。

http://gyazo.com/95cd94db39b407e7961355b20da8fc67.png

  • 演習5.6をやってみよう

while文をfor文に変えてみる

解答例:

class Kinri {
public static void main (String args[]) {
	double okane=100000;
	int year;
	for(year=1;okane < 200000; year++) {
		okane = okane * 1.05;
		System.out.println("year = " + year + "  okane= " + okane);
	}
}
}

モンテカルロ法で円周率を計算してみる(ループの練習)

  • 1x1の正方形のエリアにランダムに矢を当てた場合、1/4円の中に当たる矢の数は、 面積に比例すると考えられます。あたりの矢の割合を調べれば円周率がわかります。

http://gyazo.com/e4f68c7ed1045c10801ec201ed00b5e6.png

  • MonteCarlo?.java というファイルを作ります。
  • まずは100個乱数を表示するプログラムを作ってみましょう。
class MonteCarlo {  
public static void main (String args[]) {
	int i;
	for(i=0;i<100;i++)
        System.out.println(Math.random());
        }
}

矢の落下点x,yをランダムな位置にするには、乱数で指定します。 これがあたりかどうかは、原点からの距離で調べます

			x = Math.random();
			y = Math.random();
			if(x*x + y*y < 1)  hit++;
  • 100個の矢、1000個の矢などいろいろためしてで円周率を計算してみてください
  • 解答例です
class MonteCarlo {
	public static void main (String args[]) {
		int i;
		double hit = 0;
		double x, y;
		for(i=0;i<1000;i++) {
			x = Math.random();
			y = Math.random();
			if(x*x + y*y < 1) {
				hit++;
			}
		}
		System.out.println(4 * hit / 1000);	
	}
}

for-each文は新しい手法なので練習しましょう

  • プログラム5.7の代わりに以下をやってみよう
class ArrayTest {  
public static void main (String args[]) {
	int[] vec = new int[3];
	vec[0]=1;
	vec[1]=2;
	vec[2]=3;
	for (int x: vec) {
	     System.out.println(x);
	     }
       }
}

演習

mainの引数argsは、Stringの配列で、コマンドラインで起動したとき、 コマンドの後に続けた書いた文字が入っています。 args[0], args[1], args[2] .... をすべてfor-each文で 表示するプログラムを書いてみましょう。

http://gyazo.com/8d8effac163e0dc939e74f237d8507b1.png

ヒント:for(String s: args)を使います

  • 解答例
class ArgsTest2 {  
public static void main (String args[]) {
	for(String s: args) 
	    System.out.println(s);
       }
}

第6章 クラスの基礎

クラスとインスタンスの説明をしました

  • クラスは型、インスタンスはそれから作られたもの
    • クラスがたいやきの焼き型だとすると、インスタンスはそれから作られたたいやき
    • クラスは設計図でインスタンスはそれから作られたもの
  • クラスとインスタンスそれぞれにメソッドと変数がある
    • クラス変数 例:何個のインスタンスを作ったか?
    • クラスメソッド 例:インスタンスを作れ
    • インスタンス変数 例:ひとつのたいやきの重さ
    • インスタンスメソッド 例:たいやきをxxグラム食べる

http://gyazo.com/bbdd3587977a172f7fa7f00c4f5787e0.png

  • 演習問題6.1, 6.2, 6.3

例えば以下のような実行結果が出るようにしてください

http://gyazo.com/deeb78a70a724a01ce76945235d42ab8.png

public static void main の説明をしました

  • javaコマンドは、引数のクラスのクラスメソッドmainを実行します
    • staticと付いているのがクラス変数、クラスメソッドの印です
  • Pointクラスにクラスメソッドmainを実装すれば自分自身をテストできます
  • クラスPoint3Dに自分自身をテストするクラスメソッドmainを作ってみよう

http://gyazo.com/bdef2ab8e69f7f6e62273c2d67d7af2e.png

変数にはメソッド経由でアクセスするのが良いという説明をしました

  • 変数の型などを将来変更してもメソッドの書き換えで対応できます
public class Point {
	private int x, y;
	void set(int newx, int newy) {x=newx; y=newy;}
	int getx() { return x;}
	int gety() { return y;}

	void print () {
		System.out.println(x + ", " + y);
	}

	public static void main(String argv[]) {
		Point pt1= new Point();
		Point pt2 = new Point();
		pt1.set(10,20);
		pt2.set(-pt1.getx(), -pt1.gety());
		pt1.print();
		pt2.print();
	}

}
  • Point3Dのメソッドを充実させて次のmain()メソッドで
10, 20, 30
-10, -20, -30

という結果が出るようにしましょう

       public static void main(String argv[]) {
               Point3D pt1 = new Point3D();
               Point3D pt2 = new Point3D();
               pt1.set(10, 20, 30);//インスタンス変数を設定
               pt2.set(-pt1.getx(), -pt1.gety(), -pt1.getz());
               pt1.print();//インスタンスメソッド呼出
               pt2.print();

       }
  • Point3Dに、他の点との距離を返すメソッド distance ( Point3D p ) を実装して、次のmain()メソッドで
10, 20, 30
-10, -20, -30
74.83314773547883

という結果が出るようにしましょう

       public static void main(String argv[]) {
               Point3D pt1 = new Point3D();
               Point3D pt2 = new Point3D();
               pt1.set(10, 20, 30);//インスタンス変数を設定
               pt2.set(-pt1.getx(), -pt1.gety(), -pt1.getz());
               pt1.print();//インスタンスメソッド呼出
               pt2.print();

               System.out.println(pt1.distance(pt2));

       }
  • 解答例
	
	double distance ( int ptx, int pty, int ptz ) {
		int dx = ptx - this.x;
		int dy = pty - this.y;
		int dz = ptz - this.z;
		return  Math.sqrt(dx * dx + dy * dy + dz * dz);
	}
	
	double distance ( Point3D p ) {
		return this.distance(p.getx(), p.gety(), p.getz());
	}

第7章 クラスとオブジェクトの操作

他の点との距離を返すメソッドの例を説明しました

	double distance ( int ptx, int pty ) {
		int dx = ptx - this.x;
		int dy = pty - this.y;
		return  Math.sqrt(dx * dx + dy * dy);
	}
	
	double distance ( Point p ) {
		return this.distance(p.getx(), p.gety());
	}

distanceという名前は同じでも、引数の違いで、異なる動作をさせることができます。

Osaifuクラスを作ってみよう

  • Osaifuクラスからはインスタンスがたくさん作られる
    • Osaifuクラスはお財布の設計図/工場、ここから実際のお財布(インスタンス)が複数作られる
    • 工場出荷時の残金は0円だけど、その後、いろいろな値になるだろう(お金持ちのお財布には残金が多いだろうし、逆ならば少ないだろう)
    • ということで残金はインスタンス変数とすべきだろう
  • Osaifuクラスには次のメソッド、変数が必要だろう
    • 残金を表すインスタンス変数 int okane
    • お金を入金するインスタンスメソッド void in(int x);
    • お金を出金するインスタンスメソッド int out(int x); 戻り値は実際に出金できた金額(残金が不足ならばあるだけしか出せない)
    • 残金を印刷するインスタンスメソッドがあってもよいだろう void print();
      http://gyazo.com/bd6eaafd220dc7ff791288089f293b28.png
  • Osaifuクラスをテストするmain()メソッドでは次のことをやってください
    • Osaifuインスタンスを一つ作ってそれをsaifu1という名前にする
    • Osaifuインスタンスをもう一つ作ってそれをsaifu2という名前にする
    • saifu1に1000円入金する
    • saifu2に500円入金する
    • saifu1とsaifu2が持っている金額を印刷する
    • saifu1から200円出金してそれをsaifu2に入金する
    • saifu1とsaifu2が持っている金額を印刷する
	public static void main(String argv[]) {
		Osaifu saifu1 = new Osaifu();
		Osaifu saifu2 = new Osaifu();
		saifu1.in(1000);
		saifu2.in(500);
		saifu1.print();
		saifu2.print();
		saifu2.in(saifu1.out(200));
		saifu1.print();
		saifu2.print();
	}

http://gyazo.com/c618901458edc1ba338cab87d2810157.png

  • Osaifu.java 解答編
public class Osaifu {
	int okane;	
	public void in (int x) { okane += x; }
	public int out(int x) { okane -= x; return x; }
	public void print() {
		System.out.println( "okane = " + okane +" yen");
	}
	
	public static void main(String argv[]) {
		Osaifu saifu1 = new Osaifu();
		Osaifu saifu2 = new Osaifu();
		saifu1.in(1000);
		saifu2.in(500);
		saifu1.print();
		saifu2.print();
		saifu2.in(saifu1.out(200));
		saifu1.print();
		saifu2.print();
	}
}
  • このプログラムでは残金がマイナスになってしまってもかまわない設計になってしまっています。実際には残金だけの金額しか出せないはずなので、outメソッドを改良して、残金以上の金額を要求されたら、残金分だけしか出さないように変更してみてください。
  • このためには、例えばoutメソッドを以下のようにすれば良い
	public int out(int x) {
		if(x < okane ) {
			okane = okane -x;
			return x;
		} else {
			int nokori = okane;
			okane =0;
			return nokori;
		}
	}	

つぎにOsaifuクラスにコンストラクタを追加してみよう

  • Osaifu() で残金0のインスタンスを作る
  • Osaifu(int x) で引数を残金の初期値としたインスタンスを作る

ことができるコンストラクタを作ろう。

これをmainから呼んで、上記のプログラムと同じことをするためには、

		Osaifu saifu1 = new Osaifu(1000);//インスタンスを作る
		//最初の保持金額を1000円にする
		Osaifu saifu2 = new Osaifu(500);//インスタンスを作る
		//最初の保持金額を500円にする

とすることになる。

コンストラクタ解答編

以下のコンストラクタを作ることになる。

	Osaifu() { okane = 0; }
	Osaifu(int x) { okane = x; }

これは以下のように書いても良い。

	Osaifu() { this(0); }
	Osaifu(int x) { okane = x; }

第8章 継承

継承の話をしました。 別のクラスを継承することで、 差分だけを書いて機能を拡張していくことができます。

http://gyazo.com/2c8ef14d8be63b9fc18c58d79f2f3879.png

Osaifuクラスを継承してOsaifuUSDクラスを作ってみよう

  • OsaifuUSDクラスはアメリカで買い物をするときに便利な、アメリカドルでお金を出し入れできる財布です。
  • あたらしく追加するメソッドは以下です
    • void inUSD(int x) xドルをお財布に入金します。このとき円に換算して残高に追加します
    • int outUSD(int x) xドルをお財布から出金します。このとき円に換算した金額だけ残高が減ります。戻り値はドルにしましょう。
    • 1ドルは90円にしてください
  • OsaifuUSDクラスをテストするmain()メソッドでは次のことをやってください
    • OsaifuUSDインスタンスを一つ作ってそれをsaifu1という名前にする
    • OsaifuUSDインスタンスをもう一つ作ってそれをsaifu2という名前にする
    • saifu1に1000円入金する
    • saifu2に5ドル入金する
    • saifu1とsaifu2が持っている金額を印刷する
    • saifu1から2ドル出金してそれをsaifu2に入金する
    • saifu1とsaifu2が持っている金額を印刷する
  • 動作例

http://gyazo.com/f51ea5895aaab32bb30b9a940d91515d.png

  • ヒント:一行目はこれ
public class OsaifuUSD extends Osaifu {
  • ヒント:mainはこんな感じ
	public static void main(String argv[]) {
		OsaifuUSD saifu1= new OsaifuUSD();
		OsaifuUSD saifu2=new OsaifuUSD();
		saifu1.in(1000);
		saifu2.inUSD(5);
		saifu1.print();
		saifu2.print();
		saifu2.inUSD(saifu1.outUSD(2));
		saifu1.print();
		saifu2.print();
	}
  • 解答例
public class OsaifuUSD extends Osaifu {

	public int outUSD(int usd) {
		okane-=usd * 90;
		return usd;
	}

	public void inUSD(int usd) {
		okane+=usd * 90;
	}
	
	public static void main(String argv[]) {
		OsaifuUSD saifu1 = new OsaifuUSD();
		OsaifuUSD saifu2 = new OsaifuUSD();
		saifu1.in(1000);
		saifu2.inUSD(5);
		saifu1.print();
		saifu2.print();
		saifu2.inUSD(saifu1.outUSD(2));
		saifu1.print();
		saifu2.print();
		
	}
}

OsaifuUSDクラスの改造(1)

親のメソッドを活用しても良い

public class OsaifuUSD extends Osaifu {

	public int outUSD(int usd) {
		return ( out( use * 90) / 90 );
	}

	public void inUSD(int usd) {
		in( usd * 90 );
	}
	
…

}

親のメソッドを呼ぶことを明示的に書くためにsuper.をつかってもよい。

public class OsaifuUSD extends Osaifu {

	public int outUSD(int usd) {
		return ( super.out( use * 90) / 90 );
	}

	public void inUSD(int usd) {
		super.in( usd * 90 );
	}
	
…

}

OsaifuUSDクラスの改造(2)

OsaifuUSDにprint()メソッドを追加して、 円表示の次の行に ( xxx USD ) と残高をUSD表示するようにしてください。 円表示を行う部分はスーパークラスOsaifuのインスタンスメソッドprint()を利用することを考えてみてください。

http://gyazo.com/39a7b24a8c45e15ac55693592c2eb7cf.png

  • 解答例
	public void print() {
		super.print();
		System.out.println("( " + (okane / 90) + " usd )" );
	}

小テスト練習

以下のプログラムの中で、 クラス、インスタンス、サブクラス、スーパクラス、クラスメソッド、インスタンスメソッドがどれであり、 インスタンス化、継承がどこで行われているのか確認してください。 (importで始まる一行目はまだ説明していない内容なので小テストでは扱いません。無視してください)

import javax.swing.JFrame;

 public class SampleWindow extends JFrame {
	public static void main(String args[]) {
		SampleWindow w = new SampleWindow();
 		w.setVisible(true);
	}
 }

第9章 エラーと例外処理

次のプログラムを作って試してください。 引数が少ないとエラーが出るのを確認してください。

public class TestException {
	public static void main(String argv[]){
			System.out.println(argv[0]+" "+argv[1]);
			System.out.println("Nice to meet you.");
	}
}

エラーが出る可能性のある場所をtryでくくっておき、 エラーが出たらそれを細くする処置をcatchで指定します。

public class TestException {
	public static void main(String argv[]){
		try{	
			System.out.println(argv[0]+" "+argv[1]);
			System.out.println("Nice to meet you.");
		}
		catch (Exception e) {
			System.out.println("please input 2 words.");
		}
	}
}

第10章 Stringクラスとコレクションフレームワーク

入力した文字を逆に出力するプログラムを作る

[e100:?/Documents/java] siio% java TestString ochanomizu
ochanomizu
uzimonahco
[e100:?/Documents/java] siio% 

このソースは、

public class TestString {
	public static void main (String argv[]) {
		try{
			System.out.println(argv[0]);
			int len = argv[0].length();
			for(int i = len - 1; i>=0; i--) {
				System.out.print(argv[0].charAt(i));
			}
			System.out.println();
		}
		catch (Exception e) {
			System.out.println("please input a word");
		}
	}
}

である。

Linked List の練習

サンプルプログラムを実行するときは、

	LinkedList<String> list = new LinkedList<String>(); 

などと定義すると良い。

program 10.2 改造

Alice --> Bob --> Cindy --> DaveというLinkedList?をつくって、 それからtoArray()メソッドでString配列を作ってfor each文で要素を印刷する

import java.util.*;

public class LinkedListTest{

        public static void main(String[] argv) {

                LinkedList<String> list = new LinkedList<String>();
                list.add("Alice");
                list.add("Bob");
                list.add("Dave");
                list.add("Cindy");

                Object[] names = list.toArray();

                for(Object s: names ) System.out.println(s);

        }

}

Hash Mapの練習

プログラム10.4を参考にして、 以下のように動作する英語ー日本語単語変換プログラムを作れ。

[e100:?/Documents/java] siio% java EtoJ banana
バナナ
[e100:?/Documents/java] siio% java EtoJ apple
りんご
[e100:?/Documents/java] siio% java EtoJ 
Please input an English word

ヒント:

import java.util.*;

public class EtoJ{

public static void main(String args[]) {
	HashMap<String,String> map = new HashMap<String,String>();
	
	map.put("apple","りんご");
	map.put("banana","バナナ");
	map.put("orange","みかん");
	map.put("pineapple","パイナップル");
	map.put("grape","ぶどう");
	map.put("peach","もも");
	map.put("melon","メロン");
	map.put("lemon","レモン");
	
	try {
	System.out.println(map.get(args[0]));
	}
	catch(Exception e) {
	System.out.println("Please input an English word");
	}

	}
}

第11章 入出力

整数を出力する例

import java.io.*;

public class DoutTest {
	public static void main (String[] args) {
		try {
			FileOutputStream fout = new FileOutputStream("dout.dat");
			DataOutputStream dout = new DataOutputStream(fout);
			dout.writeInt(100);
			dout.close();
			
		}catch (Exception e) {
			System.out.println(e);
		}
	}
}

これでdout.datという名前のファイルができあがるはずです。 作ったファイルを

od -h dout.dat

または

hexdump dout.dat

してみてください

e100:java siio$ hexdump dout.dat 
0000000 00 00 00 64                                    
0000004

整数を入出力する例

import java.io.*;

public class DoutTest {
	public static void main (String[] args) {
		try {
			FileOutputStream fout = new FileOutputStream("dout.dat");
			DataOutputStream dout = new DataOutputStream(fout);
			dout.writeInt(100);
			dout.close();
			
			FileInputStream finput = new FileInputStream("dout.dat");
			DataInputStream dinput = new DataInputStream(finput);
			System.out.println(dinput.readInt());
			dinput.close();
			
		}catch (Exception e) {
			System.out.println(e);
		}
	}
}

宿題:演習11.1 をやってください

作ったファイルを

od -h dout.dat

または

hexdump dout.dat

してみてください

解答例

import java.io.*;

public class En111 {
	public static void main (String[] args) {
		int i;
		try {
			FileOutputStream fout = new FileOutputStream ("dout.dat");
			DataOutputStream dout = new DataOutputStream(fout);
			for(i=1;i<101;i++) dout.writeInt(i);
			dout.close();
			
			FileInputStream fin = new FileInputStream ("dout.dat");
			DataInputStream din = new DataInputStream(fin);
			
			for(i=1;i<101;i++) System.out.println(din.readInt());
			din.close();
			
		} catch (FileNotFoundException e) {
			System.out.println(e);
		} catch (IOException e) {
			System.out.println(e);
		}
	}
}

プログラム11.3をやってみてください

作ったファイルを

od -h 

または

hexdump

してみてください

http://gyazo.com/74c061dfe2fcd6b72885878f867c78ba.png

import java.io.*;

public class PrintWriterTest{
	public static void main(String[] args) {
		try {
		//writer.txtというファイルを作って文字を書き込む
			FileWriter fwriter = new FileWriter("writer.txt");
			PrintWriter pwriter = new PrintWriter(fwriter);
			pwriter.println(2006);
			pwriter.println("Java教科書");
			//fwriter.write("Java教科書");
			pwriter.close();	
		}
		catch (IOException e) {
			System.out.println(e);
		}
	}
}

つぎに、プログラム11.4を参考にして、 このPrint Write Testに書き足して、 書き込んだデータを読み出して画面に表示するプログラムを作ってください。

ヒント:

import java.io.*;

public class PrintWriterTest{
	public static void main(String[] args) {
		try {
		//writer.txtというファイルを作って文字を書き込む
			FileWriter fwriter = new FileWriter("writer.txt");
			PrintWriter pwriter = new PrintWriter(fwriter);
			pwriter.println(2006);
			pwriter.println("Java教科書");
			//fwriter.write("Java教科書");
			pwriter.close();	
			 
			 
			 ここに書き足す
			 
			 
		}
		catch (IOException e) {
			System.out.println(e);
		}
	}
}

文字ストリームをファイルに書いて読み込むプログラム

import java.io.*;

public class PrintWriterTest{
	public static void main(String[] args) {
		try {
		//writer.txtというファイルを作って文字を書き込む
			FileWriter fwriter = new FileWriter("writer.txt");
			PrintWriter pwriter = new PrintWriter(fwriter);
			pwriter.println("java 教科書" + 2001 );
			pwriter.close();			
		//writer.txtのファイルの中身をSystem.out.printlnで表示する
			FileReader freader = new FileReader("writer.txt");
			BufferedReader breader = new BufferedReader(freader);
			String tmp;
			while( (tmp=breader.readLine() ) != null) {
				System.out.println(tmp);
			}
			breader.close();
		}
		catch (IOException e) {
			System.out.println(e);
		}
	}
}

プログラム11.5をやってこれを拡張して演習11.2をやってください

キーボードから1行入力された文字列によるテキストファイルを作る

http://gyazo.com/f9aee7f492d574f870e85e2022df374c.png

ヒント

 import java.io.*;
 
 public class En112 {
 	public static void main(String[] args) {
 	
 		try {


ここにプログラムを書く
 		
 			}
			catch(IOException e) {
 				System.out.println(e);
  			}
    }
 }

解答例

import java.io.*;

public class En112 {
	public static void main(String[] args) {
	
		try {
			InputStreamReader ireader = new InputStreamReader (System.in);
			BufferedReader breaderK = new BufferedReader(ireader);
			String line = breaderK.readLine();
			
			FileWriter fwriter = new FileWriter("writer.txt");
			PrintWriter pwriter = new PrintWriter(fwriter);
			pwriter.println(line);
			pwriter.close();
			
			FileReader freader = new FileReader("writer.txt");
			BufferedReader breaderF = new BufferedReader(freader);
			
			String tmp=null;		
			while(  (tmp=breaderF.readLine())  != null)
				System.out.println(tmp);
			
			breaderF.close();
		
			}
			catch(IOException e) {
				System.out.println(e);
			}
	}
}

http://www.ocha.ac.jp/の内容を表示するプログラムを書いてみよう

http://gyazo.com/13044fdd9d372118a1f6fe93896eadb3.png

ヒント1

import java.net.*;

が必要です。

URL targetURL = new URL("http://www.ocha.ac.jp/");

でURLクラスのインスタンスが得られる。

InputStream istream = targetURL.openStream();

でこれからInputStream?のインスタンスが得られる。

InputStreamReader isreader = new InputStreamReader(istream);

でこれからInputStreamReader?のインスタンスが得られる。

BufferedReader breader = new BufferedReader(  isreader );

でこれからBufferedReader? のインスタンスが得られる。

ヒント2

import java.io.*;
import java.net.*;

public class URLTest {
	public static void main (String argv[]) {
		try {
			
			 
			 ここにプログラムを書く
			 
			 
		} catch (IOException e) {
			System.out.println("error...");
		}
	}
}

ヒント3:

import java.io.*;
import java.net.*;

public class URLTest {
	public static void main (String argv[]) {
		try {
			URL targetURL = new URL("http://www.ocha.ac.jp/");
			InputStream istream = targetURL.openStream();
			InputStreamReader isreader = new InputStreamReader(istream);
			BufferedReader breader = new BufferedReader(  isreader );
		
ここで一行ずつ読み込む

		} catch (IOException e) {
			System.out.println("error...");
		}
	}
}

解答例:

import java.io.*;
import java.net.*;

public class URLTest {
	public static void main (String argv[]) {
		try {
			URL targetURL = new URL("http://www.ocha.ac.jp/");
			InputStream istream = targetURL.openStream();
			InputStreamReader isreader = new InputStreamReader(istream);
			BufferedReader breader = new BufferedReader(  isreader );
		
			String line;
			while((line=breader.readLine()) != null) System.out.println(line);
		
		} catch (IOException e) {
			System.out.println("error...");
		}
	}
}

写真ファイルのダウンロード

http://siio.jp/cat.jpg 

をダウンロードして、cat.jpgというファイルを作るプログラムを作ってください。 データはテキストじゃなくて、バイナリーです。

ヒント1:

InputStream?のインスタンスに対してread()メソッドを使うと1バイトのデータが得られます。読み終わると-1になります。 1バイトのデータを書き出すなら、FileOutputStream?だけで可能です。

ヒント2:

import java.io.*;
import java.net.*;

public class URLJpeg {
	public static void main (String argv[]) {
		try {
			URL targetURL = new URL("http://siio.jp/cat.jpg");
			InputStream istream = targetURL.openStream();
			
			FileOutputStream fout = new FileOutputStream("cat.jpg");

というインスタンスを作って、

istream.read()

で読んで、

fout.write(1バイト)

で書き出します。

解答例

import java.io.*;
import java.net.*;

//http://siio.jp/cat.jpg
//をダウンロードして、cat.jpgというファイルを作るプログラム

public class URLJpeg {
	public static void main (String argv[]) {
		try {
			URL targetURL = new URL("http://siio.jp/cat.jpg");
			InputStream istream = targetURL.openStream();
			
			FileOutputStream fout = new FileOutputStream("cat.jpg");
			
			int aData;
			while((aData  = istream.read()) != -1) fout.write(aData);
			
			istream.close();
			fout.close();
			
			
		} catch (IOException e) {
			System.out.println("error...");
		}
	}
}

本日のレポート

上記のプログラム(URLJpeg.java, URLJpeg.class) を、出席番号+名前のフォルダにいれて、ZIP圧縮して提出してください。`

写真読み込みの高速化

上記の例では写真データを1バイトずつ読み書きしていました。 InputStream?のメソッドを調べると、複数バイト単位で読み込むメソッドがあります。 たとえば、512バイトずつ読み書きすることで、処理速度が向上すると期待できます。 そこで、複数バイト読み書きするよう、上記のプログラムを変更して、 実際にどの程度(実行速度にして何倍くらい)性能向上するか確認してみましょう。

read

public int read(byte[] b)
         throws IOException
入力ストリームから配列長さだけのバイト数を読み込もうとし、それをバッファ配列 b に格納します。
実際に読み込まれたバイト数は整数として返されます。
戻り値は、バッファに読み込まれたバイトの合計数。ストリームの終わりに達してデータがない場合は -1

を使って読みこみ、

write

public void write(byte[] b,
                  int off,
                  int len)
           throws IOException
指定された byte 配列の、オフセット位置 off から始まる len バイトを出力ストリームに書き込みます。

を使ってください。

  • ヒント
byte[] data = new byte[512];

という配列を用意して、

	int datalength;
	while(( datalength=istream.read(data)) != -1) fout.write(data, 0, datalength);

とします。

  • 解答例
import java.io.*;
import java.net.*;

//http://siio.jp/cat.jpg
//をダウンロードして、cat.jpgというファイルを作るプログラムを作ってください。
//データはテキストじゃなくて、バイナリーです。

public class URLJpeg2 {
	public static void main (String argv[]) {
		byte[] data = new byte[512];
		try {
			URL targetURL = new URL("http://siio.jp/cat.jpg");
			InputStream istream = targetURL.openStream();
			
			FileOutputStream fout = new FileOutputStream("cat.jpg");
			
			int datalength;
			while(( datalength=istream.read(data)) != -1) fout.write(data, 0, datalength);
			
			istream.close();
			fout.close();
			
			
		} catch (IOException e) {
			System.out.println("error...");
		}
	}
}

ここでは512バイトを読み込むことにしました。でも、InputStream?のメソッドを見ると、available()というのがあります。

available()
この入力ストリームのメソッドの次の呼出しによって、ブロックせずにこの入力ストリームから読み込むことができる(またはスキップできる)推定バイト数を返します。

これを使えば、適切な長さを見積もれるかもしれません。

引数のURLをファイルにするプログラムを考えてみましょう

curlというコマンドがあります。

curl http://ocha.ac.jp/

などとすると、htmlが見られますし、

curl http://siio.jp/cat.jpg > cat.jpg

などとすると、ファイルとして保存できます。これに近いプログラムを作ってみましょう。

宿題

上記の引数のURLをファイルにするプログラムを作ってください。 また、cat.jpgのファイル取得でまとめて読むことでどれくらい速度が改善したかを、 レポートにしてください。レポートの書式は任意です。(テキストファイルでかまいません)

これらのjava, class, レポートのファイルをまとめて、出席番号+名前のフォルダに入れて、圧縮して、12月10日の授業の開始時間に提出してください。

第12章 Swing

とても簡単なウィンドウ

import javax.swing.JFrame;
public class SimpleWindow {

       public static void main(String argv[]) {
               JFrame f = new JFrame("私が作った最初の窓");
               f.setSize(200,100); 
               f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               f.setVisible(true);
       }
}

JFrameを継承するプログラミング

import javax.swing.JFrame;
public class SimpleWindow extends JFrame {

	public void initialize () {
		this.setTitle("私が作った最初の窓");
		this.setSize(200,100);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
	}

	public static void main (String argv[]) {
		SimpleWindow sw = new SimpleWindow();
		sw.initialize();
	}
}

ラベルを表示するウィンドウ

プログラム12.1を参考にして、上記の、継承を使ったプログラムによるウィンドウの中に、 Hello!という文字を出してみよう。

http://gyazo.com/c6efe47de19436f7564660377fe8b98c.png

解答例:

import javax.swing.*;
import java.awt.*;

public class SimpleWindow extends JFrame {

	public void initialize () {
		this.setTitle("私が作った最初の窓");
		
		JLabel label = new JLabel("Hello!");
		Container container = this.getContentPane();
		container.add(label);
		this.pack();
		
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String argv[]) {
		SimpleWindow sw = new SimpleWindow();
		sw.initialize();
	}

}

ボタンを2個表示するウィンドウ

プログラム12.2をみてください。 getContentPane?()で得られたContainerに直接ボタンを貼付けることもできますが、 貼付けられるのは一つのボタンだけのようです。 そこで、JPanel (パネル) に2個のボタンを貼付け、それをContainerに貼付けることで複数のボタンを表示しています。

http://gyazo.com/03c28df2419065241b8736b7b69d7fd3.png

プログラム12.2を参考にして、継承を使ったプログラムによるウィンドウの中に、 2個のボタンを出してみよう。

http://gyazo.com/4c3086ae9b6b5434d2ea741369f731c5.png

解答例:

import javax.swing.*;
import java.awt.*;

public class SimpleButton extends JFrame {

	public void initialize () {
		this.setTitle("私が作った最初の窓");
		
		JPanel panel = new JPanel();
		JButton button1 = new JButton("button1");
		JButton button2 = new JButton("button2");
		panel.add(button1);
		panel.add(button2);
		Container container = this.getContentPane();
		container.add(panel);	
	
		this.pack();		
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String argv[]) {
		SimpleButton sw = new SimpleButton();
		sw.initialize();
	}

}

このプログラムでは,ボタンを押しても何もおこりません.

ボタンが押されたイベントを受け取るためには,

  1. ActionListener?をimplementしたクラスを作る
  2. そのインスタンスを作る
  3. これをボタンにaddActionListener?()で登録する 必要があります.

プログラム12.3を参考に,ボタンを押したらprintlnで次のようなメッセージを表示するプログラムを作ってみましょう.

http://gyazo.com/67d27d0588f4dd5d11410e1107165994.png

ヒント(最初の6行です)

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SimpleButton extends JFrame implements ActionListener {

JButton button1, button2;

	public void initialize () {

解答例

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SimpleButton extends JFrame implements ActionListener {

JButton button1, button2;

	public void initialize () {
		this.setTitle("私が作った最初の窓");
	
		JPanel panel = new JPanel();
		button1 = new JButton("button1");
		button2 = new JButton("button2");
		button1.addActionListener(this);
		button2.addActionListener(this);

		panel.add(button1);
		panel.add(button2);
		Container container = this.getContentPane();
		container.add(panel);
	
		this.pack();		
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public void actionPerformed (ActionEvent e) {
		if(e.getSource()==button1) 
			System.out.println("Hello");
		else
			System.out.println("Goodbye");
	}

	public static void main(String argv[]) {
		SimpleButton sw = new SimpleButton();
		sw.initialize();
	}

}

宿題:プログラム12.4

宿題:プログラム13.1のようにボタンを配置して、それぞれを押すと、それぞれのボタンの名前が表示されるプログラムを作ってください。

まずは、プログラム12.4を見て、上記のプログラムを拡張して5個のボタンに対応して, WEST, EAST, SOUTH, NORTH, CENTERと表示されるプログラムをつくってください。さらにこれを拡張して、プログラム13.1のようなボタンを配置して、それぞれを押すと、それぞれのボタンの名前が表示されるプログラムを作ってください。次回の授業で提出お願いします。

なお、以下のようにすると、ボタンの名前を印刷することができます。

        public void actionPerformed(ActionEvent e){
                System.out.println(((JButton)e.getSource()).getText());
        }

第13章 様々なコンポーネントとレイアウト

プログラム13.1の説明図

http://gyazo.com/649bbe400f96c8c31923bcf7e5aebbd4.png

13.2節を読んで,プログラム13.2を実行させてください

ボタンが一つしかないプログラムなので、ActionPerformed?の中で、 ボタン種類のチェックを省略してしまっているところが特徴です。

演習13.1をやってください

こんなのをつくってください。

http://gyazo.com/999f1e766551a994186cc3d159bde0bf.png

BorderLayout?でもできるようですが、私はGridLayour?使ってみました。

 		panel.setLayout(new GridLayout(2,2));
		panel.add(textleft);
		panel.add(textright);
		panel.add(button);
		panel.add(clearbutton);

ボタンが複数になるので、ActionPerformed?の中で、ボタンを区別する必要があります。 演習ができそうにないという人は、飛ばして、次に進んでください。

解答例

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class JTextFieldSample extends JFrame implements ActionListener {
	JButton button, clearButton;
	JTextField textleft, textright;
	
	JTextFieldSample(String title) {
		setTitle(title);
		button = new JButton("left to right");
		clearButton = new JButton("clear");
		button.addActionListener(this);
		clearButton.addActionListener(this);
		
		textleft = new JTextField(10);
		textright = new JTextField(10);
		JPanel panel=new JPanel();
		panel.setLayout(new GridLayout(2,2));
		panel.add(textleft);
		panel.add(textright);
		panel.add(button);
		panel.add(clearButton);
		Container container=this.getContentPane();
		container.add(panel);
	}
	
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==(button)) {
			textright.setText(textleft.getText());
			textleft.setText("");
		}else if(e.getSource()==(clearButton)) {
			textright.setText("");
		}
	}
	
	public static void main(String[] args) {
		JTextFieldSample sample = new JTextFieldSample("JTextFieldSample");
		sample.pack();
		sample.setVisible(true);
		sample.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}

どのボタンからのイベントであるかを識別する方法

  • プログラム12.3では
    • ボタンへの参照を、action Performedから参照できる変数に入れて
    • action Performedの中で、e.get Source()してButtonのインスタンスを得て比較している
  • プログラム12.4では、
    • 準備として button.set Action(button.get Text());でボタン文字をactionとして設定して
    • action Performedの中で e.get Action Command()でアクションを得て文字比較している
  • ということで以下のようなことも可能8
    • acttion Performedの中で、get Source()してボタンを得る
    • そのボタンからget Textしてボタンの文字列を得て文字比較する
    • ただし、get Sourceで得られるのはボタンの親クラスなのでButtonにキャストする
    • 以下をaction Performedのなかで試してみよう
      System.out.println((JButton)(e.getSource()).getText());

13.5節を読んで,プログラム13.5を実行してください

http://gyazo.com/dd4e103c011682b3a78b9ed0c8d5134b.png

http://gyazo.com/4755cce7280963b32050db455d265cc1.png

メニューアイテムにcommandという情報をつけて、ActionPerformed?ではこれを使ってメニュー項目を区別しています。

演習13.2をやってください(メニュー項目は何でも良いです)

演習ができそうにないという人は、飛ばして、次に進んでください。

http://gyazo.com/2d9c3b6534e7b87fcd3ec22be00d5fed.png

13.6節を読んで,プログラム13.6を実行してください

教科書203ページのプログラム13.6の5行めのところに、

... implements ActionListener6: {

とありますが、これは、

... implements ActionListener {

の間違いのようです。

終章 おまけ

マウスイベント

マウスイベントを受け取るには、Mouse ListenerやMouse Motion Listenerなどをインプリメントします。 以下のようにするとイベントをうけとれるます。

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class MouseTest extends JFrame implements MouseListener, MouseMotionListener{
	
	public void mouseClicked(MouseEvent e) {
		System.out.println("mouse clicked!");
	}
	public void mouseEntered(MouseEvent e) {
		System.out.println("mouse entered!");
	}
	public void mouseExited(MouseEvent e) {
		System.out.println("mouse exited!");
	}
	public void mousePressed(MouseEvent e) {
		System.out.println("mouse pressed!");
	}
	public void mouseReleased(MouseEvent e) {
		System.out.println("mouse released!");
	}
	public void mouseDragged(MouseEvent e) {
		System.out.println("mouse dragged!");
	}
	public void mouseMoved(MouseEvent e) {
		System.out.println("mouse moved!");
	}
	
	public static void main(String[] args) {
		MouseTest test = new MouseTest();
		test.setTitle("MouseTest");
		test.addMouseListener(test);
		test.addMouseMotionListener(test);
		test.setSize(400,300);
		test.setVisible(true);
		test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
}

サウンドファイルを再生する

  • 以下のファイルをダウンロードしてください。

http://siio.jp/lecture/Sounds/Ping.aiff

(他にも、Basso.aiff Frog.aiff Hero.aiff Pop.aiff Submarine.aiff Blow.aiff Funk.aiff Morse.aiff Purr.aiff Tink.aiff Bottle.aiff Glass.aiff Ping.aiff Sosumi.aiff を置いておきました)

これを再生するプログラムを作ってみましょう。以下で再生できます。(2015年は音が出なかった)

import java.io.*;
import javax.sound.sampled.*;

public class AudioPlay {
	public static void main(String[] args)  {
       	try{
          		File audioFile = new File("Ping.aiff");
           		AudioFormat format = AudioSystem.getAudioFileFormat(audioFile).getFormat();
          		DataLine.Info info = new DataLine.Info(Clip.class, format);
           		Clip clip = (Clip)AudioSystem.getLine(info);

	    		clip.open(AudioSystem.getAudioInputStream(audioFile));
           		clip.start();
	    		clip.drain();
	    		clip.close();
        	}
        	catch(Exception e){
             		e.printStackTrace();
       	}
	}
}

他の環境でのGUIプログラミングの例

X11

以下の内容の新しいファイル,buttontest.cを作ってください. printfの逆スラッシュが正しくコピペできてないかもしれないので,注意してください. 入力が面倒なら,添付ファイルの buttontest.c をダウンロードしてください.

#include <X11/Xlib.h>
#include <stdio.h>
 
int main (){
	Display *display = XOpenDisplay (NULL);
	XEvent event;
	Window window = XCreateSimpleWindow(display, DefaultRootWindow(display),0,0,150,100,0,0,0);
	XSelectInput(display,window,KeyPressMask | ButtonPressMask |  ButtonReleaseMask);
	XMapWindow(display, window);
	XFlush(display);

	while(1) {
		XNextEvent(display,&event);
		switch (event.type) {
		  case KeyPress: 
			printf("key\n");
			break;
		  case ButtonPress:
			printf("button down\n");
			printf("button\n");
			break;
		  case ButtonRelease:
			printf("button up\n");
			break;
		}
	}
	return 0;
}

以下のコマンドでコンパイルしてください.

cc -L/usr/X11R6/lib -I/usr/X11R6/include buttontest.c -lX11

出来上がったファイルを,./a.outで実行してください.

Mac OS X

How2MacOSXProgramming を見てください

iPhone

How2iPhoneProgramming? を見てください

簡単なアニメーション

  • まずはなにもしないウィンドウを出します
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class SimpleAnime extends JFrame {

	private void init() {
		this.setTitle("SimpleAnime");
		this.setSize(300,200);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public static void main(String[] args) {
		SimpleAnime frame = new SimpleAnime();
		frame.init();
	}
}
  • 次に動くボールを出します
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class SimpleAnime extends JFrame {
	JPanel panel;
	Graphics g;
	
	private void init() {
		this.setTitle("SimpleAnime");
		this.setSize(300,200);
		panel = new JPanel();
		this.getContentPane().add(panel);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		g=panel.getGraphics();
		g.setColor(Color.blue);

		int x=0, xdelta=10;
		while(true) {
			g.fillOval(x,80,50,50);
			try{Thread.sleep(50);}catch(Exception e){}
			g.clearRect(x, 80, 52,52);
			x+=xdelta;
			if(x>250) xdelta=-10;
			if(x<0) xdelta=10;
		}
		
	}
	
	public static void main(String[] args) {
		SimpleAnime frame = new SimpleAnime();
		frame.init();
	}
}

http://gyazo.com/12d1f047af8d4f87f7199c8a7db66080.png

  • マルチスレッド化する

上記のプログラムでは、main()で、frame.init()したあと、このメソッドで無限にアニメーション書き換えを行うことになります。なので、二度とmain()には戻ってきません。(以下で示した、メニューは、また別のスレッドで動くので、このままでも動きます)

アニメーションだけをするなら、これでも良いのですが、他にも仕事をしたい場合には難しいですし、やれないことはないですが、タイミングを計るのが難しいです。ということで、アニメーションする部分は、別のスレッドにして、そちらに任せてしまうのが通常です。

以下のように、別のインスタンスを別スレッドで動かします。別スレッドで動かすインスタンスを作るために、Animatorという名前のクラスを用意しました。別スレッドで動かすためには、Runnableをimplementする必要があります。ここで必須のrunというメソッドが、裏で実行されるので、そこに、上記のプログラムのアニメーション描画部分をそっくり移動させます。Graphics gの情報を伝えておく必要があるので、それを設定するメソッドも作りました。アニメーションしつつ、main()の方で数字を表示しています。

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.lang.Thread;

class Animator implements Runnable {
	Graphics g;

	public void setGraphics(Graphics animeG) {
		g=animeG;
	}

	public void run() {
		int x=0, xdelta=10;
		while(true) {
			g.fillOval(x,80,50,50);
			try{Thread.sleep(50);}catch(Exception e){}
			g.clearRect(x, 80, 52,52);
			x+=xdelta;
			if(x>250) xdelta=-10;
			if(x<0) xdelta=10;
		}
	}
}

class SimpleAnime extends JFrame {
	JPanel panel;
	Graphics g;
	Animator animator;
	
	private void init() {
		animator=new Animator();
		this.setTitle("SimpleAnime");
		this.setSize(300,200);
		panel = new JPanel();
		this.getContentPane().add(panel);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		g=panel.getGraphics();
		g.setColor(Color.blue);
		
		animator.setGraphics(g);
		new Thread(animator).start();
	}
	
	public static void main(String[] args) {
		SimpleAnime frame = new SimpleAnime();
		frame.init();
		
		for(int i=0;;i++) {
			System.out.println(i);
			try {Thread.sleep(500);}catch(Exception e){}
		}
	}
}
  • アニメーションボールの設定ができるアプリケーションを作ってみよう

こういうのを作ってほしい

http://lab.siio.jp/index.php?plugin=attach&pcmd=open&file=SimpleAnime.class&refer=Lecture

ヒント:上のアニメーションのプログラムに、メニューを取り付けて、 action Performedでメニューからのイベントを受け取れば良いです。 メニューの動きは、プログラム本来の動きと並列に動いてくれるので、 上のアニメーションのようなアニメーション以外何もできない手抜きアニメーションでも、 メニューは動いてくれます。

ヒント: action Performed ではこうしたら良い

public void actionPerformed(ActionEvent e) { 
		String command = e.getActionCommand(); 
		if(command=="red") g.setColor(Color.red); 
		if(command=="blue") g.setColor(Color.blue); 
  • 余力があれば、ボールが当たったら音が出るようにしてみよう。

ヒント:メニューはSimple Animeでつくって、action listenerをanimatorにしました。メニューを作るところがながいので、メソッドに分けました。

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.lang.Thread;

class Animator implements Runnable, ActionListener {

略			
	public void actionPerformed(ActionEvent e) { 
		String command = e.getActionCommand(); 
		if(command !=null) { 
			System.out.println(command); 
		} 
		if(command=="red") g.setColor(Color.red); 
		if(command=="blue") g.setColor(Color.blue); 
		if(command=="yellow") g.setColor(Color.yellow); 
		if(command=="fast") xdelta=30; 
		if(command=="slow") xdelta=5; 
	} 

略

}

class SimpleAnime extends JFrame  {

略

	 
	private void makeMenu() { 
		JMenuBar menubar = new JMenuBar(); 
		JMenu menu = new JMenu("color"); 
		JMenu menuSpeed = new JMenu("speed"); 
		 
		JMenuItem item1 = new JMenuItem("red"); 
		item1.addActionListener(animator); 
		item1.setActionCommand("red"); 
		JMenuItem item2 = new JMenuItem("blue"); 
		item2.addActionListener(animator); 
		item2.setActionCommand("blue"); 
		JMenuItem item3 = new JMenuItem("yellow"); 
		item3.addActionListener(animator); 
		item3.setActionCommand("yellow"); 
		menu.add(item1); 
		menu.add(item2); 
		menu.add(item3); 
		 
		JMenuItem item4 = new JMenuItem("fast"); 
		item4.addActionListener(animator); 
		item4.setActionCommand("fast"); 
		JMenuItem item5 = new JMenuItem("slow"); 
		item5.addActionListener(animator); 
		item5.setActionCommand("slow"); 
		menuSpeed.add(item4); 
		menuSpeed.add(item5); 
	 
		menubar.add(menu); 
		menubar.add(menuSpeed); 
		this.setJMenuBar(menubar);
	} 

略	

}
  • ボールの色と早さをメニューで指定する(解答編)

上記のプログラムにメニューを追加して、 ボールの色と速さをメニューで指定するようにしました。 メニューはメインのJFrameインスタンスで作ってこれに貼りつけていますが、 Action Listenerは、別スレッドで動いているAnimatorクラスのインスタンスとしました。

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.lang.Thread;

class Animator implements Runnable, ActionListener {
	Graphics g;
	int xdelta =5;

	public void setGraphics(Graphics animeG) {
		g=animeG;
	}
			
	public void actionPerformed(ActionEvent e) { 
		String command = e.getActionCommand(); 
		if(command !=null) { 
			System.out.println(command); 
		} 
		if(command=="red") g.setColor(Color.red); 
		if(command=="blue") g.setColor(Color.blue); 
		if(command=="yellow") g.setColor(Color.yellow); 
		if(command=="fast") xdelta=30; 
		if(command=="slow") xdelta=5; 
	} 
	
	public void run() {
		int x=0;
		while(true) {
			g.fillOval(x,80,50,50);
			try{Thread.sleep(50);}catch(Exception e){}
			g.clearRect(x, 80, 52,52);
			x+=xdelta;
			if(x>250) xdelta=-xdelta;
			if(x<0) xdelta=-xdelta;
		}
	}
}

class SimpleAnime extends JFrame  {
	JPanel panel;
	Graphics g;
	Animator animator;
	 
	private void makeMenu() { 
		JMenuBar menubar = new JMenuBar(); 
		JMenu menu = new JMenu("color"); 
		JMenu menuSpeed = new JMenu("speed"); 
		 
		JMenuItem item1 = new JMenuItem("red"); 
		item1.addActionListener(animator); 
		item1.setActionCommand("red"); 
		JMenuItem item2 = new JMenuItem("blue"); 
		item2.addActionListener(animator); 
		item2.setActionCommand("blue"); 
		JMenuItem item3 = new JMenuItem("yellow"); 
		item3.addActionListener(animator); 
		item3.setActionCommand("yellow"); 
		menu.add(item1); 
		menu.add(item2); 
		menu.add(item3); 
		 
		JMenuItem item4 = new JMenuItem("fast"); 
		item4.addActionListener(animator); 
		item4.setActionCommand("fast"); 
		JMenuItem item5 = new JMenuItem("slow"); 
		item5.addActionListener(animator); 
		item5.setActionCommand("slow"); 
		menuSpeed.add(item4); 
		menuSpeed.add(item5); 
	 
		menubar.add(menu); 
		menubar.add(menuSpeed); 
		this.setJMenuBar(menubar);
	} 
	
	private void init() {
		animator = new Animator();
		this.setTitle("SimpleAnime");
		this.setSize(300,200);
		this.makeMenu();
		panel = new JPanel();
		this.getContentPane().add(panel);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		g=panel.getGraphics();
		g.setColor(Color.blue);
		
		animator.setGraphics(g);
		new Thread(animator).start();
	}

	public static void main(String[] args) {
		SimpleAnime frame = new SimpleAnime();
		frame.init();
		
		for(int i=0;;i++) {
			System.out.println(i);
			try {Thread.sleep(500);}catch(Exception e){}
		}
	}
}

http://gyazo.com/d5db8ca6fa153520e94ee7d2b7a93915.png

  • この先改良すべきこと [#u99ec852]

アニメーションの途中で、ボールがちらつくことがあります。 ボールの場所を矩形で消して、新しいボールを描いているので、 その途中の作業が見えてしまうからです。 これを無くすには、ダブルバッファの手法を用います。 すなわち、描画する面をもう一枚用意して、 そちらに描画し、 描画が終わったところで、一気に更新する方法です。

ダブルバッファの手法は、授業の最終課題である「お絵かきプログラム」のところで説明します。

線を引く簡単なプログラム

JPanelのサブクラスを作りました。

import javax.swing.JPanel;
import java.awt.Graphics;

public class DrawPanel extends JPanel {

	public void drawLine(int x1, int y1, int x2, int y2){
		Graphics g = this.getGraphics();
		g.drawLine(x1, y1, x2, y2);
	}
 }

こちらはメインのプログラム。JFrameのサブクラスで、これに上記のJPanelのサブクラスを貼付けます。 リスナーになっているので、こちらでマウスなどのイベントを受け取ります。

import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;

public class SimpleDraw extends JFrame implements MouseMotionListener {

	int lastx=0, lasty=0, newx, newy;
	DrawPanel panel;
 

	public void mouseMoved(MouseEvent arg0) {
       }

	public void mouseDragged(MouseEvent arg0) {
		newx=arg0.getX();
		newy=arg0.getY();
		panel.drawLine(lastx,lasty,newx,newy);
		lastx=newx;
		lasty=newy;
	}


	private void init() {
		this.setTitle("Simple Draw");
		this.setSize(300, 200);
		this.addMouseMotionListener(this);
		panel=new DrawPanel();
		this.getContentPane().add(panel);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public static void main(String[] args) {
		SimpleDraw frame=new SimpleDraw();
		frame.init();
	}

}

Java Appletの作り方

いままでは、Java Applicationを作ってました。 これはjavaコマンドから実行するアプリケーションでした。 このほか、Javaには、Java Appletという実行形式式があります。 Appletは、webページなどで動かすことができます。 もともとは、webサービスでクライアント側でアプリケーションを動かすために 開発されました。

AppletはAppletクラスを継承して作ります。 Appletクラスは、java.awt.Panelを継承しています。 なにができるのかは、java のマニュアルをみてください。

たとえば、次のようなプログラムをAppletTest?.javaとして作ります。 これをコンパイルします。

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

public class AppletTest extends Applet {
    public void paint(Graphics g) {
        g.drawString("Hello World!!", 60, 30);
    }
}

これはhtmlの中から呼び出すことができます。 たとえば、つぎのような、index.htmlをつくります。

<html>
<head><title>Applet Test</title></head>
<body>

<applet code="AppletTest.class" width="300" height="150">
</applet>

</body>
</html>

これを、さきほどコンパイルしたclassと同じディレクトリにおいて、 webブラウザで開くと、java appletのプログラムが動きます。

http://gyazo.com/637225a1c08bef7e853944ad9b8ed390.png

または、このhtmlファイルをアップレットビューアでみることもできます。

appletviewer index.html 

などして動作を確認できます。

http://gyazo.com/d8174aace858dc50e603ee0fef62bcf7.png

つぎのようにすれば、上の先の例で示す、お絵描きプログラムも作ることができます。 init()は、起動したときに最初に一度だけ呼び出されるメソッドです。

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

public class AppletTest extends Applet implements MouseMotionListener {

int lastx,lasty,newx,newy;
Graphics g;
   
    public void mouseMoved(MouseEvent arg0) {
    }

    public void mouseDragged(MouseEvent arg0) {
	newx=arg0.getX();
	newy=arg0.getY();
	g.drawLine(lastx,lasty,newx,newy);
	lastx=newx;
	lasty=newy;
    }

    public void paint(Graphics g) {
	g.drawString("Hello World!!", 60, 30);
    }

    public void init() {
	g=this.getGraphics();
	this.addMouseMotionListener(this);
    }

}

appletviewerで見てみます。

http://gyazo.com/2c88f97c8f7234e5e3eb72dcd9b2713a.png

webブラウザでもみてみましょう。 (注意:Safariでは、読み込まれたappletが残っていますので、 更新したappletを試すためには、 Safariを一旦終了して起動しなおしてください。)

http://gyazo.com/143be91363a277f04a0fa8b1f5d5a43a.png

webサーバにおけば、世界中から使うこともできます。以下をクリックしてみてください。

http://siio.jp/lecture/applet/

Eclipseを使ってみよう

http://gyazo.com/4383db7fb81f9eacbf5cc959ff77a33d.png

  • Eclipseの警告を消す方法
	private static final long serialVersionUID = 42L;

という変数を定義しておきます。


マルチメディアプログラミングの最終課題

  • 課題:お絵描きプログラムを作成してさらに取扱説明書を作成して1月31日までに提出すること
    • この課題のヒントは SimpleDraw をみてください。

提出課題として最低やってほしいこと

  • ペンの太さをメニューで変えられるようにしてください
  • ペンの色をメニューとカラーパレットで変えられるようにしてください
  • 消しゴム機能を追加してください
  • ウィンドウの大きさを変えても絵が消えてしまわないようにする (ダブルバッファを使う)

機能拡張:以下のことができれば加点します

  • 絵や写真のファイルを取り込めるようにする
  • いろいろな効果のペンを作る(たとえばペンの動きに従って文字が出る)
  • 絵をファイルへ書き出す機能を作る
  • 他の絵データをスタンプのように押す機能
  • コピーアンドペースト
  • メニューバーだけでなく、スライダ、ボタン、別ウィンドウ(パレット)などを使って使いやすくする
  • そのほか、世の中のお絵描きプログラムにありそうな機能を実現する

機能拡張の詳細はSimpleDraw

を見てください。SimpleDrawのページでは、

  • 機能の拡充
  • 使いやすさの追求

の2通りの拡張を書いてあります。どちらの方針で進めていただいても結構です。 説明書に、工夫したところを書いておいてください。

取扱説明書の作り方

  • ApplicationsからMicrosoft Office 2011/Microsoft Wordもしくは、テキストエディット(Text Edit)を選択して、これを使って、今回作成したプログラムの取扱説明書を書いてください。他のアプリで作ってもらっても良いですが、最後にPDFにしておいてもらえると助かります。
  • せっかくですので作った機能はぜんぶここで説明してください。(プログラムは私も試してみますが機能を見逃すかもしれません)
  • スクリーンキャプチャした図も入れてください。図は次のようにして作ります
    • スクリーンキャプチャしたいところで、コマンド(リンゴマーク)+シフト+3を押します。すると画面全体のスクリーンショットがとれます
    • もしくは、コマンド(リンゴマーク)+シフト+4を押すとマウスドラッグで任意の場所の部分的なスクリーンショットがとれます
    • もしくは、コマンド(リンゴマーク)+シフト+4を押し、さらにスペースキーを押し、任意のウィンドウをクリックすると、そのウィンドウのスクリーンショットがとれます
    • 以上の操作で、デスクトップにピクチャファイルができます。これをWordかText Editにドラッグアンドドロップします。
    • もしくは、デスクトップのピクチャファイルをダブルクリックで開き、欲しい部分を矩形ツールで選択してコピーし、WordかText Editにペーストします
  • Control キーを押しながらキーボードショートカットを押すと、画像はファイルではなく、クリップボードに保存されるので、直後に書類にペーストできます。
  • がんばったところ、大変だったところなどを書いていただいても結構です。また、できれば自力でやって欲しいのですが、だれかに教えてもらったり、web上のサンプルプログラムを参考にした場合は、そのことを説明書に書いてください。また、クラスメートににプログラムを教えた場合も、だれのどこを手伝ったかを書いておいてください。

出来上がったプログラムの提出方法

  • フォルダを作ってその中にjavaファイルとclassファイルと、取扱説明書ファイルと、それ以外に必要なファイルがもしあればそれらを入れてください。フォルダの中のclassファイルをダブルクリックしたらプログラムが起動することを確認してください。
  • このフォルダに名前を付けてください。フォルダの名前は、「出席番号+氏名(ローマ字の性か名)+必要ならばバージョン番号の数字」にしてください。
  • このフォルダを圧縮してください
  • このフォルダを圧縮してください
  • 圧縮したファイルを
    /home/isstaff/siio/Public/Drop Box/.
    に提出してください。ターミナル.appからなら
    cp 123456siioitiro.zip /home/isstaff/siio/Public/Drop\ Box
    としてください。ファインダーからなら、メニューから「移動」「フォルダへ移動...」を選んで 以下のように入力して、移動ボタンを押して、そこに現れるドロップボックスホルダに、ドラッグアンドドロップしてください。 http://siio.jp/gyazo/dropbox.png
    • 書き込み専用なので確認できないけどokですかという意味のダイアログが出るかと思いますが問題ありません。
  • レポート提出用フォルダは書き込み専用で見ることができません。アップロードできたかどうか不安でしたら教員まで質問してください。
  • 同じ名前のフォルダを投げ込むと、エラーになります。ということで新しいバージョンができたら別の名前のフォルダを作って提出し直してください。(フォルダ名最後に数字をつけてください)

締切

  • 締め切りは1月30日11:59pmとします
    • この日までに提出してください

昨年度の優秀作品例



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-10-11 (木) 14:58:04 (6d)