Lecture

Java プログラミング入門

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

javaのマニュアル

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

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

http://is.ocha.ac.jp/~siio/gyazo/dropbox.png

教科書

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://is.ocha.ac.jp/~siio/gyazo/7366bfab668207c6598c4d88ef70d2d4.png

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

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

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

https://coteditor.com/archives.ja

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

class Hello {  
public static void main (String args[]) {
        System.out.println("hello java world!");
        }
}

http://is.ocha.ac.jp/~siio/gyazo/20121004010107.png

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章

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

ヒント

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章

第5章

演習

乱数を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");
		}
	}
}

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

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);
	}
}
}

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

http://gyazo.com/e4f68c7ed1045c10801ec201ed00b5e6.png

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++;
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文は新しい手法なので練習しましょう

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章 クラスの基礎

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

http://gyazo.com/bbdd3587977a172f7fa7f00c4f5787e0.png

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

http://gyazo.com/deeb78a70a724a01ce76945235d42ab8.png

クラス変数・メソッドとインスタンス変数・メソッド

public static void 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();
	}

}
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();

       }
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クラスを作ってみよう

	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

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();
	}
}
	public int out(int x) {
		if(x < okane ) {
			okane = okane -x;
			return x;
		} else {
			int nokori = okane;
			okane =0;
			return nokori;
		}
	}	

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

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

これを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クラスを作ってみよう

http://gyazo.com/f51ea5895aaab32bb30b9a940d91515d.png

public class OsaifuUSD extends Osaifu {
	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();
		
	}
}

為替レートを90円にしたが、多分現在の為替レートとはかけ離れていると思う。 為替レートを変数として持たせるとしたら、どうしたら良いだろうか。

のどちらにするか、考えてみよう。

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クラスとコレクションフレームワーク

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

最初の引数(文字列)を表示するプログラムを作る。クラス名はTestString

public class TestString {

	public static void main(String argv[]) {
		System.out.println(argv[0]);
	}

}

演習10.1改:最初の引数(文字列)を逆に出力するプログラムを作る

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

さらには、引数がない場合は引数入力を促すことを表示してみよう。

[e100:?/Documents/java] siio% java TestString
please input a word
[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 FoutTest {
	public static void main(String[] args) {
		try {
			FileOutputStream fout = new FileOutputStream("fout.dat");
			fout.write(1234);
			fout.close();
		}
		catch (IOException e) {
			System.out.println(e);
		}
	}
}

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

od -h fout.dat

または

hexdump fout.dat

してみてください

$ hexdump fout.dat 
0000000 d2                                             
0000001

1234は0x4d2だったのでその下1バイトが書き込まれました。

整数を出力する例

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 Writer 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://is.ocha.ac.jp/~siio/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://is.ocha.ac.jp/~siio/cat.jpg");
			InputStream istream = targetURL.openStream();
			
			FileOutputStream fout = new FileOutputStream("cat.jpg");

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

istream.read()

で読んで、

fout.write(1バイト)

で書き出します。

解答例

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

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

public class URLJpeg {
	public static void main (String argv[]) {
		try {
			URL targetURL = new URL("http://is.ocha.ac.jp/~siio/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のメソッドを調べると、複数バイト単位で読み込むメソッドがあります。 たとえば、1024バイトずつ読み書きすることで、処理速度が向上すると期待できます。 そこで、複数バイト読み書きするよう、上記のプログラムを変更して、 実際にどの程度(実行速度にして何倍くらい)性能向上するか確認してみましょう。

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[1024];

という配列を用意して、

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

とします。

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

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

public class URLJpeg2 {
	public static void main (String argv[]) {
		byte[] data = new byte[1024];
		try {
			URL targetURL = new URL("http://is.ocha.ac.jp/~siio/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...");
		}
	}
}

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

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

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

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

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

curl http://ocha.ac.jp/

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

curl http://is.ocha.ac.jp/~siio/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();
	}

}

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

上記のプログラムのJPanelのところをJButtonにしてみましょう。

解答例:

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

public class SimpleWindow extends JFrame {

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

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

}

http://is.ocha.ac.jp/~siio/index.php?plugin=attach&pcmd=open&file=button.png&refer=How2JavaProgramming

ボタンを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();
	}

}

ここではボタンを区別するために、インスタンス(への参照)を比較した。それ以外の方法もある。 一つは、ボタンのテキストを入手することである。ボタンのテキストを入手してそれを比較しても良い。 ボタンのテキストを表示するだけなら以下のようにしても良い。

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

もう一つは、ボタンにコマンドを書く方法である。 ボタンにsetActionCommand(String)を定義しておくと、getActionCommand()で知ることができる。

button1.setActionCommand("hello");

としておけば、actionPerformedの中で

e.getActionCommand();

で文字列を得られる。例えば、

        public void actionPerformed(ActionEvent e){
                System.out.println(e.getActionCommand());
        }

でコマンド部分を印刷できる。

プログラム12.4をやってください。

演習12.2(改)

上で作った二つのボタンのプログラムに対して、レイアウトマネージャのFlowLayoutを使って、左寄せ、センタリング、右寄せを試してください。

演習のヒント

		bt1 = new JButton("button1");
		bt2 = new JButton("button2");
		panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
		bt1.setActionCommand("this is b1");
		bt2.setActionCommand("this is b2");

FlowLayoutにはCENTER, LEFT, RIGHTなどの揃え方の指定がありますが、これをコンストラクタの引数で指定できるようです。addのところではレイアウト指定しないようです。

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

プログラム13.1の説明図

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

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

ヒント:プログラム12.4を見て、上記のプログラムを拡張して5個のボタンに対応して, WEST, EAST, SOUTH, NORTH, CENTERと表示されるプログラム作るとわかりやすいかもしれません。そうすれば、プログラム13.1のボタンの名前を表示するプログラムが作りやすいと思います。

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

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

プログラム12.4は継承を使っていないので以下のように書き直します。

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

public class ComplicatedLayoutSample extends JFrame implements ActionListener {
	
	public void initialize() {
		JPanel panel1 = new JPanel();
		JPanel panel2= new JPanel();
		JPanel panel3= new JPanel();
		JPanel panel4= new JPanel();
		JPanel panel5= new JPanel();
		
		panel1.setLayout(new FlowLayout());
		for (int i=1; i<=3; i++) {
			panel1.add(new JButton("NORTH" + i));
		}
		panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
		for (int i=1; i<=3; i++) {
			panel2.add(new JButton("WEST" + i));
		}		
		panel3.setLayout(new GridLayout(3,2));
		for (int i=1; i<=6; i++) {
			panel3.add(new JButton("CENTER" + i));
		}	
		panel4.setLayout(new BorderLayout());
		panel4.add(new JButton("EAST1"), BorderLayout.NORTH);
		panel4.add(new JButton("EAST2"), BorderLayout.SOUTH);		
		panel5.setLayout(new BoxLayout(panel5, BoxLayout.X_AXIS));
		for (int i=1; i<=4; i++) {
			panel5.add(new JButton("SOUTN" + i));
		}	
		
				
		Container container = this.getContentPane();
		container.add(panel1,BorderLayout.NORTH);
		container.add(panel2,BorderLayout.WEST);
		container.add(panel3,BorderLayout.CENTER);
		container.add(panel4,BorderLayout.EAST);
		container.add(panel5,BorderLayout.SOUTH);

		this.setSize(400,200);
		this.setVisible(true);
	}
	
	public void actionPerformed(ActionEvent e) {
	}
	
	public static void main(String[] args) {
		ComplicatedLayoutSample cls = new ComplicatedLayoutSample();
		cls.initialize();	
	}
}

つぎにaction listenerとして自分自身を追加します。

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

public class ComplicatedLayoutSample extends JFrame implements ActionListener {
	
	public void initialize() {
		JPanel panel1 = new JPanel();
		JPanel panel2= new JPanel();
		JPanel panel3= new JPanel();
		JPanel panel4= new JPanel();
		JPanel panel5= new JPanel();
		
		panel1.setLayout(new FlowLayout());
		for (int i=1; i<=3; i++) {
			JButton btn = new JButton("NORTH" + i);
			btn.addActionListener(this);
			panel1.add(btn);
		}
		panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
		for (int i=1; i<=3; i++) {
			JButton btn = new JButton("WEST" + i);
			btn.addActionListener(this);
			panel2.add(btn);
		}		
		panel3.setLayout(new GridLayout(3,2));
		for (int i=1; i<=6; i++) {
			JButton btn = new JButton("CENTER" + i);
			btn.addActionListener(this);
			panel3.add(btn);
		}	
		panel4.setLayout(new BorderLayout());
		JButton btn1 = new JButton("EAST1");
		btn1.addActionListener(this);
		panel4.add(btn1, BorderLayout.NORTH);
		JButton btn2 = new JButton("EAST2");
		btn2.addActionListener(this);
		panel4.add(btn2, BorderLayout.SOUTH);

		panel5.setLayout(new BoxLayout(panel5, BoxLayout.X_AXIS));
		for (int i=1; i<=4; i++) {		
			JButton btn = new JButton("SOUTN" + i);
			btn.addActionListener(this);
			panel5.add(btn);
			}	
		
				
		Container container = this.getContentPane();
		container.add(panel1,BorderLayout.NORTH);
		container.add(panel2,BorderLayout.WEST);
		container.add(panel3,BorderLayout.CENTER);
		container.add(panel4,BorderLayout.EAST);
		container.add(panel5,BorderLayout.SOUTH);

		this.setSize(400,200);
		this.setVisible(true);
	}
	
	public void actionPerformed(ActionEvent e) {
		System.out.println( ((JButton)e.getSource()).getText()   );
	}
	
	public static void main(String[] args) {
		ComplicatedLayoutSample cls = new ComplicatedLayoutSample();
		cls.initialize();	
	}
}

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

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

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

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

public class JTextFieldSample extends JFrame implements ActionListener {
JButton button;
JTextField textleft, textright;

public void initialize() {
	button = new JButton("left to right");
	button.addActionListener(this);
	textleft= new JTextField(10);
	textright= new JTextField(10);
	JPanel panel = new JPanel();
	
	panel.setLayout(new BorderLayout());
	panel.add(textleft, BorderLayout.WEST);
	panel.add(textright, BorderLayout.EAST);
	panel.add(button, BorderLayout.SOUTH);
	
	this.getContentPane().add(panel);
	
	this.setTitle("JTextFieldSample");
	this.pack();
	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	this.setVisible(true);
}

public void actionPerformed(ActionEvent e){
	textright.setText(textleft.getText());
	textleft.setText("");
}

public static void main(String[] args){
	JTextFieldSample sample = new JTextFieldSample();
	sample.initialize();
}

}

演習13.1をやってください

このプログラムに、右のテキストフィールドをクリアするclearボタンを追加してください。 こんなのをつくってください。

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);
	}
}

解答例(初期化メソッドで作る)

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

public class JTextFieldSample extends JFrame implements ActionListener {
 JButton button, clearButton;
JTextField textleft, textright;

public void initialize() {
	button = new JButton("left to right");
	button.addActionListener(this);
	clearButton = new JButton("clear");
	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);
	
	this.getContentPane().add(panel);
	
	this.setTitle("JTextFieldSample");
	this.pack();
	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	this.setVisible(true);
}

public void actionPerformed(ActionEvent e){
	if( e.getSource() == button) {
		textright.setText(textleft.getText());
		textleft.setText("");
	}else{
		textright.setText("");
	}
}

public static void main(String[] args){
	JTextFieldSample sample = new JTextFieldSample();
	sample.initialize();
}

}

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

action Performed (Action Event e) の中で、

System.out.println((JButton)(e.getSource()).getText());

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

JListの型を指定しないとコンパイラの警告が出ます。警告を出さないためには、以下のように宣言すると良いようです。

	JList<String> list = new JList<String>(data);

こんな感じです。

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

public class JListSample extends JFrame {
	
	JListSample(String title){
		String[] data = {"Iced Coffee","Iced Tea","Iced Cafe-latte","Blended Coffee","Hot Tea","Espresso","Cappuccino"};
		JList<String> list = new JList<String>(data);
		
		JScrollPane scroll = new JScrollPane(list);
		
		scroll.setPreferredSize(new Dimension(200,100));
		JPanel panel = new JPanel();
		this.getContentPane().add(scroll);
		
		this.setTitle(title);
		this.pack();
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public static void main(String[] args){
		new JListSample("List Sample");
	}
}

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

http://gyazo.com/dd4e103c011682b3a78b9ed0c8d5134b.png

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

まずはシンプルなプルダウンメニューを作ってみましょう。 このプログラムは何もしません。

http://is.ocha.ac.jp/~siio/gyazo/JMenuSample1.png

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

public class JMenuSample extends JFrame implements ActionListener {
	
public void initialize() {
	this.setTitle("MenuSample");
	
	JMenuBar menubar = new JMenuBar();
	JMenu menu = new JMenu("menu");
	
	JMenuItem item1 = new JMenuItem("Sandwiches");
	JMenuItem item2 = new JMenuItem("Side Orders");
	JMenuItem item3 = new JMenuItem("Drinks");
	
	menu.add(item1);
	menu.add(item2);
	menu.add(item3);
	
	menubar.add(menu);
	this.setJMenuBar(menubar);
	
	this.setSize(400,200);
	this.setVisible(true);
	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void actionPerformed(ActionEvent e){
}

public static void main(String[] args) {
	JMenuSample sample = new JMenuSample();
	sample.initialize();
}

}

メニューにはメニューを追加することもできます。 上でitem3をメニューに変更すると、これにitemを追加できます。

http://is.ocha.ac.jp/~siio/gyazo/JMenuSample2.png

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

public class JMenuSample extends JFrame implements ActionListener {
	
public void initialize() {
	this.setTitle("MenuSample");
	
	JMenuBar menubar = new JMenuBar();
	JMenu menu = new JMenu("menu");
	
	JMenuItem item1 = new JMenuItem("Sandwiches");
	JMenuItem item2 = new JMenuItem("Side Orders");
	JMenu item3 = new JMenu("Drinks");
	
	menu.add(item1);
	menu.add(item2);
	menu.add(item3);
	
	JMenuItem subitem1 = new JMenuItem("Iced Coffee");
	JMenuItem subitem2 = new JMenuItem("Iced Tea");
	item3.add(subitem1);
	item3.add(subitem2);
	
	menubar.add(menu);
	this.setJMenuBar(menubar);
	
	this.setSize(400,200);
	this.setVisible(true);
	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void actionPerformed(ActionEvent e){
	}
}

public static void main(String[] args) {
	JMenuSample sample = new JMenuSample();
	sample.initialize();
}

}

それぞれのitemに、フレーム自身をaction Listenerとして登録すれば、イベントを受け付けることができます。 ここでは、メニューアイテムにcommandという情報をつけて、ActionPerformedではこれを使ってメニュー項目を区別しています。

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

public class JMenuSample extends JFrame implements ActionListener {
	
public void initialize() {
	this.setTitle("MenuSample");
	
	JMenuBar menubar = new JMenuBar();
	JMenu menu = new JMenu("menu");
	
	JMenuItem item1 = new JMenuItem("Sandwiches");
	item1.addActionListener(this);
	item1.setActionCommand("Sandwiches");
	JMenuItem item2 = new JMenuItem("Side Orders");
	item2.addActionListener(this);
	item2.setActionCommand("Side Orders");
	JMenu item3 = new JMenu("Drinks");
	
	menu.add(item1);
	menu.add(item2);
	menu.add(item3);
	
	JMenuItem subitem1 = new JMenuItem("Iced Coffee");
	subitem1.addActionListener(this);
	subitem1.setActionCommand("Iced Coffee");
	JMenuItem subitem2 = new JMenuItem("Iced Tea");
	subitem2.addActionListener(this);
	subitem2.setActionCommand("Iced Tea");
	item3.add(subitem1);
	item3.add(subitem2);
	
	menubar.add(menu);
	this.setJMenuBar(menubar);
	
	this.setSize(400,200);
	this.setVisible(true);
	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void actionPerformed(ActionEvent e){
	String command = e.getActionCommand();
	if(command != null){
		System.out.println(command);
	}
}

public static void main(String[] args) {
	JMenuSample sample = new JMenuSample();
	sample.initialize();
}

}

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

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

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

他のメニューの追加も試してみましょう。例えばお支払いメニュー。

http://is.ocha.ac.jp/~siio/gyazo/JMenuSample3.png

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

ちなみに、今のjavaのバージョンではボタンの色は変わらないようです。

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

... implements ActionListener6: {

とありますが、これは、

... implements ActionListener {

の間違いのようです。

終章 おまけ

マウスイベント

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

まずはMouse Motion Listenerを試してみましょう。 マニュアル

によると、実装しないといけないメソッドはmouse Draggedとmouse Movedです。

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

public class MouseTest extends JFrame implements MouseMotionListener{
	
	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.addMouseMotionListener(test);
		test.setSize(400,300);
		test.setVisible(true);
		test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
}

次に、Mouse Listenerも実装してみましょう。マニュアル

によると、

これを追加します。宣言で

public class MouseTest extends JFrame implements MouseListener, MouseMotionListener{

として、またmainに

		test.addMouseListener(test);

を追加します。

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://is.ocha.ac.jp/~siio/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 を置いておきました)

これを再生するプログラムを作ってみましょう。以下で再生できます。

import java.io.File;
import javax.sound.sampled.*;
 
public class AudioInputStreamExample {
  public static void main(String[] args) {
 
    try {
      File file = new File("Ping.aiff");
      AudioInputStream stream = AudioSystem.getAudioInputStream(file);
      Clip clip = AudioSystem.getClip();
      clip.open(stream);
      clip.start();
 
      // sleep to allow enough time for the clip to play
      Thread.sleep(500);
 
      stream.close();
 
    } catch (Exception ex) {
      System.out.println(ex.getMessage());
    }
  }
}

他の環境での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://is.ocha.ac.jp/~siio/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

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

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

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

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://is.ocha.ac.jp/~siio/lecture/applet/

Eclipseを使ってみよう

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

	private static final long serialVersionUID = 42L;

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


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

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

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

機能拡張の詳細はSimpleDraw

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

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

取扱説明書の作り方

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

締切

昨年度の優秀作品例



添付ファイル: filebutton.png 781件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-10-22 (金) 23:32:48