Webアプリケーション開発の基礎 ~Javaによるアプリケーション開発~ ー2002年10月19・26日(土)ー Javaとオブジェクト指向プログラミング 神奈川大学工学部 窪谷浩人 e-mail:[email protected] http://eweb.n.kanagawa-u.ac.jp/~kubotani/Welcome.html Javaとオブジェクト指向プログラミング ー第1日目の内容ー §1. オブジェクト指向プログラミングの基本構造 §2. Javaプログラムの構成要素 §3. Javaを利用したCGプログラミング 描画 & GUI(Graphical User Interface) 「Frame」に 図形を描く・写真を貼る 「Frame」にGUI機能を付け加える 1. 2. 3. メニューの表示 メニューの選択で「終了」の実行 ダイアログボックスの表示・操作 §4. 総合課題:デジタルアルバムの作成 §1.オブジェクト指向プログラミングの基本構造 「オブジェクト」の発想(1) 従来の考え方 逐次処理(実行する順番に命令を与える) プログラムカウンタ メモリアドレス 命令 00000000 00000001 00000002 00000003 00000004 00000005 00000006 「コンピュータの気持ち」でプログラミング 「オブジェクト」の発想(2) 「オブジェクト」の発想 情報処理(入力⇒内部状態の変化⇒出力) する オブジェクト(=物)達が連動する と説明された上で 「どちらが元々のモデルに近いかい?」 と言われると 次のように想像してしまう。 「オブジェクト」の発想(3) 「オブジェクト」って、こういうシミュレーション!? 経済動向の予測: \110 人間のコピーロボット(オブジェクト)を作り、 初期の資金を与え経済活動させる。 \150 \90 \100 \200 \75 \500 オブジェクト指向プログラミングの基本構造(1) オブジェクト 特性:変数(内部状態)・メソッド(機能・関数) オブジェクトのメンバ メソッド メソッド 変数 メソッド メソッド ・内部状態を表す変数は外から直 接見える(参照できる)部分もある ・メソッドを通しても外から内部状態 を参照・変更可能である ・メソッドは内部状態を参照している ので、内部状態によって機能が変わ ることもある オブジェクト指向プログラミングの基本構造 (2) 「クラス」・「インスタンス」(実例)とオブジェクト間の連携 鋳型 自動車クラス 人間クラス 六角太郎 (インスタンス 名) 神大花子 (インスタンス 名) 鋳型 運転 (メッセージ) 義経号 (インスタンス 名) 「クラス」:類型化され鋳型として働くプログラム・モジュール。 「インスタンス」:クラスの変数・メソッドはインスタンスという実在を創って利 用する(除クラス変数・クラスメソッド)。 (注)サブルーチン副プログラムは、引用されて始めてメモリ領域が確保さ れる点で似ているものの、return文で領域が開放される。 他方、インスタンスは実在として存在し続ける。 オブジェクト指向プログラミングの基本構造 (3) 「オブジェクト指向」のプログラミング法 • 継承 猿クラス チンパンジークラス スーパークラス 人間クラス サブクラス サブクラスでは、スーパークラス(既存のプログラム)のメンバをそのまま引き 継いだ上で、オリジナルなメンバを追加・上書き修正し利用する。 ゼロから新作する必要がない。 • 抽象クラス(例AbstractButtonクラス) 具体的処理を記述せずメソッド名や引数のみからなる抽象メソッドを含むクラス 具体的処理は、継承を受けたサブクラスを利用者が創ってそこで定義する 作成されたサブクラスを束ねて類型化する役割 オブジェクト指向プログラミングの基本構造 (4) 「オブジェクト指向的」のプログラミング法 ・インターフェースのインプリメント: 既存のプログラムを応用する第2の方法 Javaでは継承の親は一つ(「単一継承」)。 他方、複数のインターフェースのインプリメントは可能。 継承 スーパー クラス インプリメント 定数の定義 抽象メソッドの定義 インター フェース 抽象メソッドの サブクラスA サブクラスB #気分としては、ヘッダーファイルのincludeのような感じ 実体定義 非オブジェクト指向プログラミング 継承(再定義可能)、 との比較 メソッドやコンストラ 非オブジェクト指向 オブジェクト指向 サブルーチン副プログラム による モジュール化(カプセル化) ライブラリの利用 クタの多重定義、 アクセスレベル 機能の追加拡張 変数の受け渡し が容易で、 変数の隠蔽 既存プログラムの有効活用可能 機種依存のない (Windows, X-Window, MacOS X) Windowプログラミング可能 時系列的な処理が基本 マルチスレッドによる並列処理 #ただし、コンピュータのハードウェアはノイマン型な ので、マルチスレッドは仮想的な並列処理である。プ ログラミング手法としての存在意義である。 機種依存のない窓プログラミング サンプルプログラムMenuFrame.javaの実行結果 Windows 98 MacOS 8.1 §2. Javaプログラムの構成要素(1) • クラスの書き方 クラス宣言 class クラス名 extends スーパークラス名 implements インターフェース名 { メンバ変数の定義 ・・・ コンストラクタの定義 クラス本体 ・・・ メソッドの定義 ・・・ } Javaプログラムの構成要素(2) • メンバ変数の定義 [アクセスレベル] [修飾子]データ型 変数名[ = 初期値]; #データ型:基本データ型:整数・実数・一文字・真偽値 参照データ型:reference(ポインタ)が入るので文字列や インスタンスも宣言可能 • メソッドの定義 [アクセスレベル] [修飾子] 戻り値データ型 メソッド名(データ型 引数名) { メソッド本体 } 例: public static void main(String args [] ){….} どのクラスからもアクセス可能で(public)、インスタンスを作らなくても実行でき て(static,クラスメソッド)、戻り値はなく(void)、引数は文字列の配列。 # 引数列が異なるメソッドを同じメソッド名で定義できる(「多重定義」(Overload))。 Javaプログラムの構成要素(3) • コンストラクタの定義 インスタンスの生成要求があった時に自動的に(必ず)実行され、 初期のインスタンス状態の設定に利用される。 [アクセスレベル] クラス名(データ型 引数名) { コンストラクタ本体 } 形の上ではメソッドの定義と似ているが、名前の部分がクラス名と同一。戻り値もない。 • インスタンスの生成:new演算子 new クラス名(コンストラクタの引数); 引数はコンストラクタに引き渡され、生成されるインスタンスの初期状態を設定 する Javaプログラムの構成要素(4) Staticメンバと非Staticメンバ クラスはメンバとして変数・メソッドを備えている Staticメンバ(修飾子「static」を付けて定義) クラス変数(例:Math.PI) クラスメソッド(例:Math.sqrt) ・「クラス名.メンバ名」で参照・実行される New (クラスメソッドはサブクラスに継承されない)。 ・クラスメソッドの定義中には非Staticメンバは 現れない(インスタンスを生成し利用することは可能)。 非Staticメンバ(定義文に「static」がない) インスタンス変数・インスタンスメソッド ・クラスからインスタンスを創って 変数:A.b 利用する メソッド:A.getArea ・「インスタンス名.メンバ名」で参照・ 実行される インスタンスA クラス static int a; int b; static void main( ) double getArea( ); New New 変数:B.b メソッド:B.getArea インスタンスB 変数:C.b メソッド:C.getArea インスタンスC 「オブジェクト指向」的プログラミング(1) ーオブジェクト(インスタンス)の生成ー Triangleクラス AreaMainクラス 変数:a, b, c (辺長) メソッド:Main メソッド:getArea(面積の計算) printValue 辺長の設定 辺長の参照 面積の値 インスタンス t1 インスタンス t2 サンプルプログラムAreaMain.java(1/2) class Triangle { double a, b, c; void printValue() { System.out.println(“三角形の値(" + a + "," + b + "," + c + ")" ); } double getArea() { double p; double S; Systemクラスのクラス変数outに記 録されているクラス(PrintStream) のインスタンスメソッドprintlnを実 行する p=(a+b+c)/2.0; S=Math.sqrt(p*(p-a)*(p-b)*(p-c)); return S; } } サンプルプログラムAreaMain.java (2/2) class AreaMain { public static void main( String args []) { Triangle t1 = new Triangle(); Triangle t2 = new Triangle(); t1.a = 3.0; t1.b = 4.0; t1.c = 5.0; t2.a = 1.0; t2.b = 1.0; t2.c = 1.0; new演算子によるTriangleインス タンスの生成 各インスタンスの変数の設定 t1.printValue(); t2.printValue(); 各インスタンスのメソッドの実行 double s1 = t1.getArea(); double s2 = t2.getArea(); System.out.println( "t1の面積は" + s1 + ", t2の面積は" + s2 + "です"); } } 「オブジェクト指向」的プログラミング(2) ー変数の隠蔽- アクセスレベル メンバ変数:どのクラスに参照・変更させるか メソッド・コンスタラクタ:他のどのクラスが実行できるか アクセスレベル オプション 同じ クラス private ○ サブ クラス すべての クラス × ○ protected × ○ public なし 同じ パッケージ ○ (注) ○ × (注)同じパッケージにあればサブクラスであってもアクセス許可される。 サンプルプログラムAreaMain2.java class Triangle{ private double a, b, c; アクセスレベルprivate 多クラスからの参照禁止 void setValue(double a, double b, double c){ this.a = a; this.b = b; this.c = c; } ・・・ } class AreaMain{ public static void main( String args []){ Triangle t1 = new Triangle(); Triangle t2 = new Triangle(); t1.setValue( 3.0, 4.0, 5.0); t2.setValue( 1.0, 1.0, 1.0); } ・・・ } 直接Triangleインスタンス の変数を参照できない -setValueメソッドを介在さ せてメンバ変数を設定 「オブジェクト指向」的プログラミング(3) ー継承ー Triangleクラス VolumeMainクラス 変数:a, b, c (辺長) メソッド:Main メソッド:getArea(面積の計算) 底辺長の設定 高さの設定 printValue 底辺長・高さの 参照 継承 体積の値 New Tetrahedronクラス 変数:a, b, c (底辺長),h(高さ) メソッド:getArea(底面積の計 算) getVolume(体積の計 算) New printValue サンプルプログラムVolumeMain.java (1/2) class Triangle{ 変数をサブクラスにも公開する protected double a, b, c; void setValue(double a, double b, double c){ ・・・ } void printValue(){ ・・・ } double getArea(){ ・・・ } } クラスTriangleを継承 class Tetrahedron extends Triangle{ private double h; 変数h(高さ)をメンバに追加 void setValue(double a, double b, double c, double h){ スーパークラスのメソッド super.setValue( a, b , c); 底辺の設定にはスー setValueは再定義により上 this.h = h; パークラスのメソッド 書き(Override)される } setValueを使う void printValue(){ System.out.println("4面体の値(" + a + "," + b + "," + c + "," + h + ")" ); } double getVolume(){ double S; double V; S = super.getArea(); 底辺の面積Sの計算にはスーパー V = S * h /3.0; クラスのメソッドを使う return V;} } サンプルプログラムVolumeMain.java (2/2) class VolumeMain { public static void main( String args []){ Tetrahedron t1 = new Tetrahedron(); Tetrahedron t2 = new Tetrahedron(); t1.setValue( 3.0, 4.0, 5.0, 4.0); t2.setValue( 2.0, 2.0, 2.0, 2.0); t1.printValue(); t2.printValue(); double s1 = t1.getArea(); double v1 = t1.getVolume(); double s2 = t2.getArea(); double v2 = t2.getVolume(); System.out.println( "t1の底面積は" + s1 + "、体積は" + v1 + "です"); System.out.println( "t2の底面積は" + s2 + "、体積は" + v2 + "です"); } } Javaを利用したCGプログラミング(1) 標準パッケージJava API(Application Programming Interface) パッケージ名 java.applet java.awt java.io java.lang java.math java.net java.rmi java.security java.sql java.text java.util 用途 Javaアプレット作成用 GUI機能(AWT=Abstract Window Toolkit) I/O機能 オブジェクト・文字列・数字などの基本要素定義 数学的な関数の処理など ネットワークプログラミング用 ネットワーク上でオブジェクトを操作 セキュリティ管理用 関係型データベースへのアクセス用 テキスト・日付・数値などを国・地域に依存しないデータとして処理 乱数・ハッシュテーブル・ベクトルの取り扱い Javaを利用したCGプログラミング(2) AWTからの継承の例 1. 描画プログラミング 1.1 「Frame」に基本図形を描く 1.2 画像ファイルを貼る 2. GUIプログラミング 「Frame」にGUI機能を付け加える 2.1 メニューの表示 2.2 メニューの選択で「終了」の実行 2.3 ダイアログボックスの表示・ボタンのクリック処理 1. Javaによる描画プログラミング 出発点:Windowを表示するBasicFrameクラス (BasicFrame.java) java.awtパッケージのインポート(他のパッケージ内のクラスを利用可能にする) import java.awt.*; java.awt.Frameクラスからの継承 class BasicFrame extends Frame { public static void main(String args[]) { BasicFrame BF=new BasicFrame(); クラスメソッドmainが (static)最初に外から 起動される(public) 戻り値:無し BF.setSize( 580, 460 ); BF.setVisible( true ); } } 引数:文字列の配列 new演算子による インスタンスの生成 1.1 基本図形の描画(1) 描画メソッドpaintの再定義(LineFrame.java) import java.awt.*; class LineFrame extends Frame { public void paint(Graphics g){ g.drawLine(70,50,490,120); } public static void main(String args [] ) { LineFrame LF=new LineFrame(); LF.setSize(580,460); LF.setVisible(true); } } BasicFrameに追加した 部分-Frameクラスから 継承しているメソッド paintを再定義 LineFrameインスタンス LFの生成をきっかけに paintメソッドを実行 1.1 基本図形の描画(2) (Frameの)paintメソッドの実行 public void paint(Graphics g) { g.描画命令( 引数 ); } Graphicsオブジェクトのインスタンスgを生成 Graphicsオブジェクトは、描画領域・色・フォントなどの情報をオブジェクト化 したもの Graphicsオブジェクトのメソッドで属性設定を行う • • • • g.drawLine(int x1, int y1, int x2, int y2) :(x1,y1)(x2,y2)間の直線 g.drawRect(int x, int y, int width, int height) :左上角(x,y)の矩形 g.drawOval(int x, int y, int width, int height) :左上角(x,y)の楕円 g.setColor(Color c) :色の設定 などなど Colorクラスのインスタンスc(色種もオブジェクト) 1.1 他の図形(Javaプログラム実例) Javapg03_フレームの表示とグラフィクス.ppt (By. Uchida)pp.269-298, 参照 上記へ飛ぶ 1.2 画像ファイルの描画(1) サンプルプログラムJPegFrame.java import java.awt.*; class JPegFrame extends Frame { public void paint(Graphics g) { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image =toolkit.getImage( "flower.jpg" ); g.drawImage( image, 30, 60, this); } public static void main(String args [] ) { JPegFrame JF = new JPegFrame(); JF.setSize( 630, 450); JF.setVisible(true); } } BasicFrameに 追加した部分 1.2 画像ファイルの描画(2) 1. 画像データを持つImageオブジェクト作成 Toolkit toolkit =Toolkit.getDefaultToolkit(); Image image =toolkit.getImage( “ファイル名” ); Imageクラスとは java.awt.Imageクラスのこと java.awt.Toolkitクラスの利用 java.awt.Toolkitクラスの利用 Toolkitクラスは、Javaが提 供するGUIコンポーネントと 個々の環境における Windowシステムとの仲立 ちをする 2. Imageオブジェクトの描画 GraphicsクラスのdrawImageメソッドの利用 g.drawImage(Image image, int x, int y, ImageObserver obs) g.drawImage(Image image, int x, int y, int width, int height, ImageObserver obs) 等 #1. (x,y)はイメージの左上を原点とする座標、 width, heightはイメージの矩形の幅、高さ 2. ImageObserverは、イメージのロード終了の通知を受けるオブジェクト。 画像を描かせている場合、通常、そのコンポーネント自身、つまり、thisとする。 2. JavaによるGUIプログラミング ー 「Frame」にGUI機能を付け加えるー 具体例 1 メニューの表示 プログラミングの要素 GUI要素の追加 Java.awt(サブ)パッケージの継承 により利用 2 メニューで「終了」の実行 イベント処理 3 ダイアログボックスの 表示・ボタンのクリック GUI要素のレイアウト 1.メニューの表示 「メニュー」の要素と構造 フレーム フレーム 追加(setMenuBarメソッド) メニューバー メニューバー 追加(addメソッド) メニュー メニュー 追加(addメソッド) メニュー項目 メニュー項目3つ サンプルプログラムMenuFrame.java (1/3) import java.awt.*; class MenuFrame extends Frame { public MenuFrame() { super(); setMenu(); } ・・・・ private void setMenu(){ ・・・ コンストラクタ -インスタンスが生成された時、スー パークラスFrameのコンストラクタとこの (this)クラスのsetMenuメソッドを実行 } setMenuメッソッドの定義 public static void main(String args[]) { MenuFrame MF = new MenuFrame("Menu Sample"); MF.setSize(580,460); 本体のクラスからインスタンスを MF.setVisible(true); } 生成する今までと同じmainメソッド } サンプルプログラムMenuFrame.java (2/3) setMenuメソッドの定義 private void setMenu(){ MenuItem NewCreate = new MenuItem("新規作成") ; MenuItem OpenFile = new MenuItem("開く"); MenuItem FinalExit =new MenuItem("プログラム") ; Menu FileMenu = new Menu("ファイル"); FileMenu.add( NewCreate ); FileMenu.add( OpenFile ); FileMenu.add( FinalExit ); Menu EditMenu = new Menu("編集"); EditMenu.add( new MenuItem("切り抜き") ); EditMenu.add( new MenuItem("コピー") ); EditMenu.add( new MenuItem("貼り付け") ); MenuItemに明示的な名前 を付け、それを引数として MenuインスタンスEileMenu にぶら下げる MenuItemインスタンスを次々 生成させながらMenuインスタ ンスEditMenuにぶら下げる MenuBar mb = new MenuBar(); MenuBarインスタンスmbにMenuイン mb.add(FileMenu); スタンスを登録する mb.add(EditMenu); this.setMenuBar(mb); } この(this)クラス、MenuFrameにmbをMenuBarとして追加する サンプルプログラムMenuFrame.java (3/3) 多重定義コンストラクタ (引数が違うものを並列定義) public MenuFrame() { super(); setMenu(); } public MenuFrame(String title) { super(title); setMenu(); } 明示的に定義しないとスーパークラス のコンストラクタsuper()のまま。 setMenuによるオリジナル機能の追加 引数を付けてインスタンス生成 を行うためのコンストラクタを 追加(「多重定義」(Overload)) GUIのイベント処理 因果律の流れ オブジェクト指向的理解 イベントソース・オブジェクト ボタン・メニュー項目 ユーザの操作 ボタンのクリック・メニューの選択 キー入力・ウィンドウ状態の変更など イベント・オブジェクト ボタンがクリックされること メニューが選択されること キー入力があること ウィンドウの状態が変化すること イベントの発生 イベントリスナー・オブジェクト 処理の開始 処理内容を記 述したメソッド 2.メニューで「終了」の実行(1) ActionListenerクラス フレームを描画するクラス内で生成 される「メニュー項目」インスタンスに addActionListenerメソッドを実行さ せりリスナーインスタンスを指定 インプリメント リスナーインターフェース をインプリメントしたクラス として作成 ClosingActionListener MenuFrameクラス クラス コンストラクタ イベント情報に伴い実行す る処理をメソッドとして記述 MenuItem インスタンス ActionEvent の仲介 ClosingActionListner インスタンス 2.メニューで「終了」の実行(2) (1)「終了」の実行 (I)イベントリスナークラスの定義 (II)必要なイベントメソッドの記述 public void actionPerformed(ActionEvent evt) { 「終了」のための処理の記述; } (2)メニューの選択=イベントソース (III)イベントソースへのリスナーの登録 FinalExit:イベントソースインスタンス CAL:イベントリスナーインスタンス MenuItem FinalExit = new MenuItem("プログラムの終了"); ClosingActionListener CAL = new ClosingActionListener(); FinalExit.addActionListener(CAL ); サンプルプログラムMenuExitFrame1.java (1/2) import java.awt.*; import java.awt.event.*; class MenuExitFrame extends Frame { ・・・・ } イ ベ ン ト リ ス ナ ー オ ブ ジ ェ ク ト java.awt.eventパッケージも使うので追加 インターフェースを利 用してイベント処理の 機能を追加 class ClosingActionListener implements ActionListener { ActionListnerインターフェース public void actionPerformed(ActionEvent evt) の抽象メソッドをここで具体化 (Override) { String MenuName = evt.getActionCommand(); if( MenuName.equals("プログラムの終了") ) ActionEventにソースイ { ベント情報を尋ねる System.exit(0); } Stringオブジェクトの equalsメソッドで照合 } } サンプルプログラムMenuExitFrame1.java(2/2) class MenuExitFrame extends Frame { public MenuExitFrame(){ ・・・・ } private void setMenu() { MenuItem FinalExit = new MenuItem("プログラムの終了"); ClosingActionListener CAL = new ClosingActionListener(); FinalExit.addActionListener( CAL ); ・イベントリスナー・インスタンスの生 成 Menu FileMenu = new Menu("ファイル"); FileMenu.add( FinalExit ); MenuBar mb = new MenuBar(); mb.add(FileMenu); this.setMenuBar(mb); } ・MenuItemインスタンスが発生する イベント(メニュー項目の選択)をイ ベントリスナー・インスタンスと結ぶ サンプルプログラムMenuExitFrame2.java (1/2) Frameがイベントリスナーオブジェクト import java.awt.*; import java.awt.event.*; ActionListenerをFrameがimplement class MenuExitFrame extends Frame implements ActionListener { public MenuExitFrame(){ ・・・ } private void setMenu(){ ・・・ } イベントリスナー役としてのメ ソッドの定義 public void actionPerformed(ActionEvent evt) { String MenuName = evt.getActionCommand(); if( MenuName.equals("プログラムの終了") ) { System.exit(0); } } public static void main(String args[]){ ・・・ } } サンプルプログラムMenuExitFrame2.java (2/2) import java.awt.*; import java.awt.event.*; class MenuExitFrame extends Frame implements ActionListener { public MenuExitFrame(){ ・・・ } private void setMenu(){ MenuItem FinalExit = new MenuItem("プログラムの終了"); FinalExit.addActionListener( this ); Menu FileMenu = new Menu("ファイル"); FileMenu.add( FinalExit ); MenuBar mb = new MenuBar(); mb.add(FileMenu); this.setMenuBar(mb);} public void actionPerformed(ActionEvent evt){ ・・・ } public static void main(String args[]){ ・・・ } } ・MenuItemインスタンスが発 生するイベント(メニュー項目 の選択)をイベントリスナー・ インスタンスと結ぶ (注)ここでは、イベントリス ナー・インスタンスは自分自 身のインスタンス(this) イベント処理の実装の考え方 イベントソース イベントオブジェクト ウインドウの操作 イベントリスナー メニューの選択 意図した処理の開始 ダイアローグのボタン キー入力 ActionEvent WindowEvent MouseEvent etc. イベントソースオブジェクトとイベントリスナーオブジェクトとは多対 1の関係。そこで、時間列に反して、実装はイベントリスナーから 取り掛かる方が理解は容易。 2.メニューで「終了」の実行(3) リスナークラスの構築別法 問題の所在:リスナーインターフェースが複数のリスナー メソッドを抽象メソッドとして準備している場合があり、 インプリメントによりこれを利用するするためにはすべての 抽象メソッドを明示的に具体化しなければならない。 アダプタークラスの利用 アダプタークラスのサブクラスとして リスナークラスを構築すれば、必要な 抽象メソッドの具体化だけでよい。 例: リスナー インターフェース アダプター クラス 継承 インプリメント ActionListener:リスナーメソッド1個:アダプターなし WindowListener:リスナーメソッド7個:WindowAdapter お手製の リスナークラス サンプルプログラムMenuExitFrame3.java import java.awt.*; import java.awt.event.*; class MenuExitFrame extends Frame { public MenuExitFrame(){ ・・・ } private void setMenu() { ・・・ } public static void main(String args[]) { MenuExitFrame MF = new MenuExitFrame("Menu Sample (Exit)"); ClosingListener CL = new ClosingListener(); ・イベントリスナー・インスタン MF.addWindowListener( CL ); スの生成 MF.setSize(580, 460); ・Frameサブクラスのインスタ MF.setVisible(true); ンス(MF)が発するイベント(閉 } じるボタンクリック)をイベント リスナー・インスタンスと結ぶ } class ClosingListener extends WindowAdapter { WindowAdapterを継承して public void windowClosing(WindowEvent e) イベントリスナーを導入 { System.exit(0);} } 2.メニューで「終了」の実行(4) イベントを発したMenuItemインスタンスをメ ニュー項目名で照合することが出来ない 場合はどうするの? 2.メニューで「終了」の実行(5) イベント・ソースの判定法 getActionCommand( ): ActionEventのコマンド名を返す public void actionPerformed(ActionEvent evt) { if( evt.getActionCommand().equals("プログラムの終了") ) { System.exit(0); } } getSource( ): イベントが起こったオブジェクトを返す public void actionPerformed(ActionEvent evt) { if( evt.getSource() == FinalExit ) { System.exit(0); } } MenuItemインスタンス名 問題:どうやってイベント・ソースの情報をリスナーに教える 解決策1:リスナーをフレームクラス自身が担う サンプルプログラムMenuExitFrame4.java class MenuExitFrame extends Frame implements ActionListener{ MenuItem FinalExit; ローカル変数からメンバ変数へ格上げ ・・・・ private void setMenu(){ // MenuItem FinalExit = new MenuItem("プログラムの終了"); FinalExit = new MenuItem("プログラムの終了"); FinalExit.addActionListener( this ); FileMenu.add( FinalExit );} イベントソースとリ スナーを同一のク ラスが担う public void actionPerformed(ActionEvent evt){ // if( evt.getActionCommand().equals("プログラムの終了") ) if( evt.getSource() == FinalExit ) { System.exit(0);} } 解決策2:独立リスナークラスがイベントソー スのメンバ変数を参照可能にする サンプルプログラムMenuExitFrame5.java Frameインスタンスを引数としてリス class MenuExitFrame extends Frame{ public MenuExitFrame(){ ・・・ } ナーインスタンスに渡す private void setMenu(){ FinalExit = new MenuItem("プログラムの終了"); ClosingActionListener CAL = new ClosingActionListener(this); FinalExit.addActionListener( CAL ); ・・・} public static void main(String args[]) { ・・・ } } class ClosingActionListener implements ActionListener{ MenuExitFrame MF; コンストラクタ public ClosingActionListener(MenuExitFrame f ) { MF = f; } public void actionPerformed(ActionEvent evt){ //if( evt.getActionCommand().equals("プログラムの終了") ) if( evt.getSource() == MF.FinalExit ) { System.exit(0);} } } 3.確認ダイアログの作成(1) ダイアログの仕様 1 ダイアログボックスのデザイン プログラミングの要素 Dialogクラスの継承 (DialogクラスはFrameクラスと違 いメニューを載せられない) GUI要素のレイアウト 2 メニューの「終了」選択で ダイアログボックスが現れる イベント処理 3 「OK」ボタンでプログラム終了 イベント処理 「CANCEL」ボタンでダイアログボッ クスを閉じる GUIコンポーネントの配置 土台として 必須 レイアウトマネージャ コンテナの中でのGUIコンポーネ ントの配置を管理するクラス トップレベルコンテナ setLayout add Frame Dialog Applet 中間コンテナ setLayout add Panel JScrollPane JSplitPane等 アトミックコンポーネント ・コンポーネントの固有の大きさで 横一列に配置 FlowLayout・BoxLayout ・コンテナ内で取りえる最大の大きさ に調整してコンポーネントを配置 BorderLayout ・どのコンポーネントも同じ大きさで 格子状に配置 GridLayout Label Button JCheckBox等 *コンテナ毎にデフォルトのレイアウト マネージャが設定されている。別のレ イアウトマネージャを利用するには setLayoutで明示的に設定 サンプルプログラムDialogSampleFrame.java(1/6) class ConfirmDialog extends Dialog implements ActionListener { Frame parent; Button OK_Button; メンバ変数の定義 Button CANCEL_Button; dialogClosing dC; コンストラクタの定義開始 public ConfirmDialog(Frame f) { super(f,"確認",true); Dialogクラスの引数(第1:オーナーフレーム;第 this.parent = f; 2:タイトル;第3:ture→モーダルダイアログ選択) Label MESSAGE = new Label("終了してよろしいですか?"); OK_Button = new Button("OK"); ラベルとボタンの作成 CANCEL_Button = new Button("CANCEL"); サンプルプログラムDialogSampleFrame.java(2/6) GUIコンポーネントをコンテナに次々積み重ねていく Panel BUTTONS = new Panel(); BUTTONS.add(OK_Button); BUTTONS.add(CANCEL_Button); ボタン2個をパネルに貼り付け一まと めにする Panel TotalPanel = new Panel(); ボタンをまとめたパネル とラベルをパネルに貼り TotalPanel.setLayout( new GridLayout(2,1)); 付ける TotalPanel.add( MESSAGE ); TotalPanel.add( BUTTONS ); PanelインスタンスBUTTONS は更に別のPanelインスタンス this.setLayout( new FlowLayout() ); に載せることが出来る this.add( TotalPanel ); this.setSize( 200, 100); FlowLayoutによる配置で最 終的なパネルをダイアログに ・・・・・ } コンストラクタ定義終わり } ダイアログのサブクラスの定義終わり 貼り付ける 3.確認ダイアログの作成(2) オブジェクト間の関係 Dialogクラス Frameクラス ActionEvent の仲介 DialogSample Frameクラス ActionEvent の仲介 Confirm Dialogクラス MenuItem WindowEvent の仲介 WindowEventの仲介 Window Adapter windowClosing クラス :継承(クラス間の関係) dialogClosing クラス :Eventを仲介しての インスタンス間の関係 サンプルプログラムDialogSampleFrame.java(3/6) class ConfirmDialog extends Dialog implements ActionListener { CconfirmDialogインスタン Frame parent; スをイベントリスナーにする Button OK_Button; Button CANCEL_Button; コンストラクタ内で生 dialogClosing dC; 成されたインスタンス public ConfirmDialog(Frame f){ ・・・ } を利用したいので内 部変数ではなくメンバ public void actionPerformed(ActionEvent evt) 変数にしておく { if( evt.getSource() == OK_Button ){ dsipose:Dialogの廃棄 dispose(); システム終了 System.exit(0); } else if( evt.getSource() == CANCEL_Button ){ dispose(); } } } サンプルプログラムDialogSampleFrame.java(4/6) class ConfirmDialog extends Dialog implements ActionListener { OK_Button, CANCEL_Buttonは他 Frame parent; メソッドが利用できるようにコンストラ Button OK_Button; クタの内部変数ではなくメソッド変数 Button CANCEL_Button; になっている dialogClosing dC; public ConfirmDialog(Frame f){ GUIコンポーネントの貼り付け命令群 OK_Button.addActionListener(this); CANCEL_Button.addActionListener(this); ・・・・ OK_Button,CANCEL_ Buttonの発するイベント にリスナーとしての ConfirmDialogを登録 } public void actionPerformed(ActionEvent evt){ if( evt.getSource() == OK_Button ){ ・・・} else if( evt.getSource() == CANCEL_Button ){ ・・・ } } } サンプルプログラムDialogSampleFrame.java(5/6) class dialogClosing extends WindowAdapter{ DialogWindowのタイトルバー上 Dialog d; の閉じるボタンを有効にするため WindowAdapterクラスを定義する public dialogClosing(Dialog ad){ d = ad; } public void windowClosing(WindowEvent e){ d.dispose(); } } class ConfirmDialog extends Dialog implements ActionListener{ ・・・ dialogClosing dC; public ConfirmDialog(Frame f){ Dialogサブクラスのインスタン ・・・・・ ス生成時にdialogClosingイン dC = new dialogClosing(this); スタンスを生成させイベントリス this.addWindowListener(dC) ; ナーとして登録しておく } public void actionPerformed(ActionEvent evt){ ・・・ } } サンプルプログラムDialogSampleFrame.java(6/6) class DialogSampleFrame extends Frame implements ActionListener { MenuItem FinalExit; メニューの選択でプログラムを終了さ public DialogSampleFrame(){ ・・・ } せるのではなく、今回は、ダイアログ をインスタンスとして生成させる public void actionPerformed(ActionEvent evt){ if( evt.getSource() == FinalExit ) { ConfirmDialog dlg = new ConfirmDialog(this); dlg.setVisible(true); ダイアログをインスタンス } として生成 } ダイアログの可視化 public static void main(String args[]){ ・・・ } } §4.デジタルアルバムの作成 ー1日目の課題ー • 仕様 1. 「ファイル」メニューの他、データ種 ごとに画像用のメニューを持つ。 画像用メニューにはデータ種を表 すタイトルを表示させる。 画像用メニューの項目の選択に応 じて画面中央にデータを表示させ る。 「ファイル」メニューの「プログラム の終了」項目及びウインドウの「閉 じる」ボタンにはプログラムを正常 終了させる機能を持たせる。 2. 3. 4. サンプルプログラムDigitalAlbum.java(1/3) public void paint(Graphics g) { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image =toolkit.getImage( "flower.jpg" ); g.drawImage( image, 60, 40, this); } 変更 ファイル名を変更し た上で再描画 (repaint()) イベントリスナー・クラス public void actionPerformed(ActionEvent evt) { String MenuName = evt.getActionCommand(); if( MenuName.equals("プログラムの終了") ) { System.exit(0); } else if( MenuName.equals("お花畑") ) { ;repaint(); } else if( MenuName.equals("海ホタルから横浜を眺める") ) { ;repaint(); } else if( MenuName.equals("菜の花") ) 分岐処理 { ;repaint(); } } サンプルプログラムDigitalAlbum.java(2/3) class DigitalAlbum extends Frame implements ActionListener{ int PictureNo = 0; String FileName [] = new String[ 5 ]; public DigitalAlbum( ) { ・・・ コンストラクタの中で getFileName(); ・・・ getFileNameメソッドを実行 } private void getFileName(){ FileName[0] = "flowerbet.jpg"; FileName[1] = "yokohama.jpg"; FileName[2] = "flower.jpg";} public void paint( Graphics g ) { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image =toolkit.getImage( FileName[PictureNo] ); g.drawImage( image, 30, 60, this ); } サンプルプログラムDigitalAlbum.java(3/3) class DigitalAlbum extends Frame implements ActionListener{ int PictureNo = 0; 変数PicutreNoはメンバ変 String FileName [] = new String[ 5 ]; 数なのでどのメソッドからも 参照可能 public void paint( Graphics g ) { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image =toolkit.getImage( FileName[PictureNo] ); g.drawImage( image, 30, 60, this ); } public void actionPerformed(ActionEvent evt){ String MenuName = evt.getActionCommand(); if( MenuName.equals("プログラムの終了") ) { System.exit(0); } else if( MenuName.equals("お花畑") ) {PictureNo = 0;repaint();} else if( MenuName.equals("海ホタルから横浜を眺める") ) {PictureNo = 1;repaint();} else if( MenuName.equals("菜の花") ) {PictureNo = 2;repaint();} }
© Copyright 2024 ExpyDoc