• 検索結果がありません。

第 14 回 GUI の構成とイベ ント・ドリブン

N/A
N/A
Protected

Academic year: 2021

シェア "第 14 回 GUI の構成とイベ ント・ドリブン"

Copied!
57
0
0

読み込み中.... (全文を見る)

全文

(1)

第 14 回  GUI の構成とイベ ント・ドリブン

~ GUI を使ったプログラム ( ) Ⅰ

(2)

学習目標

イベント・ドリブンプログラミングの利 点を説明できる

Swing を利用して簡単な GUI プログラ ムが書ける

簡単なカスタムウインドウを表示できる

イベントハンドラの生成・登録ができる

Model と View を分離する設計について

議論できる

(3)

GUI アプリケーション

今回はいよいよ Graphical User Interface に挑戦します

購入画面 管理画面

(4)

14.1 SwingAPI を使う

14.1.1 Swing 概要

14.1.2 Swing を使ってみよう

(5)

14.1.1 Swing 概要

Java で GUI のプログラムを書くための API

GUI

を一から作るのは大変

GUI

に関するクラス・ライブラリ群は

「 Swing

」と呼ばれている

① ウインドウを出す

② カスタムウインドウを作る

(6)

Swing 概要

すべてがオブジェクト

「コンポーネント」という

JFrame

JLabel JTextField

(7)

14.1.2 Swing を使ってみよう

import javax.swing.*;//swingクラスライブラリの利用を宣言する import java.awt.*;//swingクラスライブラリの利用を宣言する // ウインドウを表示する

public class Example14_1 { //プログラム・メイン

// フレームを起動する

public static void main(String args[]){

JFrame frame = new JFrame();//Swingで提供されるJFrameオブジェクト生成 frame.setTitle("初めてのウインドウ ");// タイトル設定

frame.setSize(200,200);//大きさ設定 frame.setLocation(50,50);//位置設定

frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);//ウインドウが閉じたときに プログラムが終了するように設定

frame.setVisible(true);//表示する }}

例題

14-1

(Example14_1.java)

① ウインドウを出す

(8)

実行結果

次はこのウインドウにボタンを

乗せてみましょう!

(9)

② カスタムウインドウを作る

ウインドウにボタンを乗せる

JFrame

を継承して、カスタムウインドウ

を作ります

J Fr ame

But t onFr ame

Swing

プログラム

表示する

()

再描画

()

など

(10)

ButtonFrame のリスト

import javax.swing.*;//swing

クラスライブラリの利用を宣言する

import java.awt.*;//swing

クラスライブラリの利用を宣言する

//JFrame

クラスを継承したカスタムフレーム(ウインドウ)クラス // ボタンが一つ乗せられている

public class ButtonFrame extends JFrame{

//

コンストラクタ

public ButtonFrame(){

getContentPane().setLayout(null);//

ウインドウに載せられるすべてのオブジェクトの位置 を自分で設定できるようにする。

// ボタンを設定する

JButton button = new JButton();//

ボタンをインスタンス化

button.setText("

初めてのボタン ");// ボタンのラベル名設定 button.setSize(150,20);// ボタンの大きさ設定

button.setLocation(20,50);// ボタンの位置設定 ( ウインドウからの相対位置 ) // ボタンをウインドウに乗せる

getContentPane().add(button);

}

例題

14-2

(ButtonFrame.java)

(11)

ButtonFrame を表示する Main

// ウインドウにボタンを乗せる

// カスタムフレーム ( ウインドウ ) の作成

public class Example14_2 {

//

プログラム・メイン // フレームを起動する

public static void main(String args[]){

JFrame frame = new ButtonFrame();//

カスタムフレームオブジェクト生成 frame.setTitle(" 初めてのウインドウ ");// タイトル設定

frame.setSize(200,200);// 大きさ設定

frame.setLocation(50,50);//

位置設定

frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);//

ウインドウが閉じたときに プログラムが終了するように設定

frame.setVisible(true);// 表示する } }

例題

14-2

(Example14_2.java)

(12)

実行結果

ボタンが乗せられました。

しかし、押しても何も起こりません。

次は、ボタンが押されたとき、プログラムを

終了するようにしましょう!

(13)

14.2 イベント・ドリブンプログラミ

ング

14.2.1 ボタンが押された時の処理を考 える

14.2.2 Java によるイベント・ドリブンプ

ログラミング

(14)

14.2.1 ボタンが

押された時の処理を考える

① 原始的な方法

ポーリング

一定期間ごとにハードウエアの状態を調べる

(15)

ハードウエアの状態を調べる

プログラム 何処にいる?

動いてないよ!

プログラム 押されてる?

“a”

が押されてます

(16)

ハードウエアを調べるプログ ラム

//Java

ではない仮想言語

public void

ボタンが押されたかどうかを調べて、押されていたら終了する

() {  マウスの位置を調べる ();

if( マウスの位置が

Button

の中にある ){

マウスの状態を調べる ();

if( マウスが押されている ){

if( 押されているのは、マウスの左ボタンである ){

プログラムを終了する }

} } } }

下記のメソッドを一定期間ごとに動か

(17)

ポーリングの問題点

考えてみよう

(18)

ポーリングの問題点

効率が悪い( CPU に負担をかける)

動いていないかもしれないのに調べる必要 がある

マウスの正確な動きを捉えるには、相当細 かい期間ごとに調べなければならない

プログラミングが大変

ややこしいメソッドを用意する必要がある

ボタンがたくさんあったら大変

(19)

② イベント・ドリブン プログラミング

イベント・ドリブン

ポーリングの問題点を解決するためのプロ グラミングスタイル

処理をイベント毎に分割して記述して、

必要に応じて呼びだされ , 処理される

(20)

イベント・ドリブンの考え方

ハードウエアを 常に見張っている 唯一のプログラム

常に見張っている

プログラム

プログラム 押されたよ!

押されたよ!

(21)

イベント・ドリブンの用語

ハードウエアを 常に見張っている 唯一のプログラム

プログラム 押されたよ!

イベント・ハンドラ イベント

イベント・ディスパッチャー

(22)

イベント・ドリブンプログラ ミング

イベントドリブン型プログラムを作る 時は、ただひたすら、イベントハンド ラをどう書くかに集中すれば良い

public void

ボタンが押されたときの処理()

{ System.exit(0);

}

これだけのメソッドを書けばよくなる

(23)

14.2.2 Java による

イベント・ドリブンプログラミ ング

① Java によるイベント・ドリブン

② イベントハンドラの作成

③ イベントハンドラの登録

Java テクニック

④ インナークラス

⑤ テキストフィールドと連動するプログラ

(24)

① Java によるイベント・ドリ ブン

Java の Swing フレームワークはこの機 能を標準で持っている

Java ではイベントハンドラのことを EventListener と呼び、オブジェクトと して表現

Java ではイベントもオブジェクトとし

て扱う (EventObject)

(25)

Java によるイベント・ドリブ ン( 2 )

ハードウエアを 常に見張っている 唯一のプログラム

プログラム

イベント・ハンドラ イベント

イベント・ディスパッチャー

押されたよ

EventObject

EventListener Swing

が提供

(26)

② イベントハンドラの作成

import java.awt.event.*;//event

クラスライブラリの利用を宣言する

// ボタンを押したときのイベントハンドラ クラス

public class ExitButtonListener implements ActionListener{

//

ボタンが押されたときのイベントハンドラ

public void actionPerformed(ActionEvent e){

System.exit(0);//

プログラムを終了する }

メソッド名はインターフェイスが }

決めているので間違えないように

ActionEvent

EventObject

サブクラスで、イベントを表すクラス

ActionListener

EventListener

の サブインターフェイス

例題

14-3

(ExitButtonListener.java)

(27)

③ イベントハンドラの登録

//JFrame

クラスを継承したカスタムフレーム(ウインドウ)クラス

public class ButtonFrame extends JFrame{

//

コンストラクタ

public ButtonFrame(){

getContentPane().setLayout(null);

// ボタンを設定する

JButton button = new JButton();

button.setText(" 初めてのボタン ");

button.setSize(150,20);

button.setLocation(20,50);

// イベントハンドラを設定する

ExitButtonListener listener = new ExitButtonListener();// イベントハンドラをインスタンス化 button.addActionListener(listener);// イベントハンドラを受信者として登録する

// ボタンをウインドウに乗せる

getContentPane().add(button);

} }

イベントハンドラを生成し、

addActionListener()

メソッドを使って 登録する

例題

14-3

(ButtonFrame.java)

(28)

実行してみましょう!

ボタンを押すと、ウインド

ウが 閉じて終了するはずです

(29)

(Java テクニック )

④ インナークラス

//JFrameクラスを継承したカスタムフレーム(ウインドウ)クラス public class ButtonFrame extends JFrame{

//コンストラクタ

public ButtonFrame(){

//ボタンを設定する //途中割愛

// イベントハンドラを設定する

ExitButtonListener listener = new ExitButtonListener();//イベントハンドラをインスタンス化 button.addActionListener(listener);//イベントハンドラを受信者として登録する

// ボタンをウインドウに乗せる

getContentPane().add(button);

}

//ボタンを押したときのイベントハンドラ インナークラス

class ExitButtonListener implements ActionListener{

//ボタンが押されたときのイベントハンドラ

public void actionPerformed(ActionEvent e){

System.exit(0);//プログラムを終了する }

}

例題

14-4

(ButtonFrame.java)

(30)

インナークラス

クラスの中にクラスを書くことができ る

Java

の便利な仕組み

インナークラスを使う利点は何でしょ

うか?

(31)

⑤ テキストフィールド と連動するプログラム

ボタンが押された時、テキストフィー ルドの内容を変更するプログラム

ボタンが押された

(32)

テキストフィールド

と連動するプログラムのリス ト

//JFrameクラスを継承したカスタムフレーム(ウインドウ)クラス public class ButtonFrame extends JFrame{

private JTextField textField = new JTextField();//テキストフィールド // コンストラクタ

public ButtonFrame(){

// ボタンを設定する ( 割愛)

// イベントハンドラを設定する ( 割愛) // ボタンをウインドウに乗せる ( 割愛) //テキストフィールドを設定する

textField.setText("ボタンは押されていません ");

textField.setBounds(20,100,150,20);//位置、大きさ設定(x,y,width,height) getContentPane().add(textField);//テキストフィールドをウインドウに載せる }

//ボタンを押したときのイベントハンドラ インナークラス

public class TextFieldChangeButtonListener implements ActionListener{

//ボタンが押されたときのイベントハンドラ

public void actionPerformed(ActionEvent e){

textField.setText("ボタンが押されました ");

}

テキストフィールドを 生成する

テキストフィールドの

内容を変更する

(33)

インナークラスの利点

簡単に他のコンポーネントと連動でき るようになる

もちろん、イベントハンドラに参照を渡す ようにして、プログラムを分割してもでき る

プログラムを分割する必要がある場合はそうす

(34)

14.3 GUI 自動販売機の構成

14.3.1 GUI 自動販売機概要

14.3.2 Model と View の分離

14.3.3 GUI 自動販売機プログラミング

(35)

14.3.1 GUI 自動販売機概要

自動販売機用コンポーネントを利用す る

基本構造

管理者用ウインドウ

(AdminFrame

クラス

)

CUI

CUIAdminApp

の機能を備えている

ユーザ用ウインドウ

(UserFrame

クラス

)

CUI

CUIUserApp

の機能を備えている

(36)

基本構造

ユーザウインドウ 管理者ウインドウ

(37)

14.3.2 Model と View の分離

① CUI 自動販売機の再利用

② Model と View の分離

③ 現状の Model の問題点

④ display() メソッドの廃止

(38)

① CUI 自動販売機の再利用

CUI アプリケーションのオブジェクト は再利用できるものがある

商品 - 製造年月日

商品種類 - 名前 - 商品番号 - 価格

商品保管庫 + 追加( )

- 価値 勘定 CUI User App

+ 追加( ) + 削除( )

CUI AdminApp 商品種類リスト

+ 追加( ) + 削除( ) 1

0. . n 1

0. . n

再利用可能

(39)

GUI 自動販売機の構成

GUI になっても構造は変わらない

商品 - 製造年月日

商品種類 - 名前 - 商品番号 - 価格

商品保管庫 + 追加( ) + 削除( )

- 価値

0. . n 1

0. . n 1

勘定 + 追加( ) + 削除( )

AdminFr ame

User Fr ame 商品種類リスト

+ 追加( ) + 削除( ) 1

0. . n 1

0. . n

(40)

② Model と View の分離

再利用できるものとできないものの違

いを考える

(41)

Model と View

再利用できるもの

自動販売機における実体や概念の構造に関 わる部分→

Model

再利用できないもの

表示に関する部分

→ View

(アプリケーションロジックに関わる部

分)

(42)

Model と View の分離

Model と View を分離しておくことに よって、表示の変更が容易になる

分離していなかったら

GUI

は始めから作り 直し

商品 - 製造年月日

商品種類 - 名前 - 商品番号 - 価格

商品保管庫 + 追加( )

- 価値

0. . n 1

0. . n 1

勘定 + 追加( ) + 削除( )

AdminFr ame

UserFr ame 商品種類リスト

+ 追加( ) + 削除( ) 1

0. . n 1

0. . n

Model

クラス群 実体や概念

View

クラス群

表示役

(43)

③ 現状の Model の問題点

ItemTypeList クラスの display() メソッ ドは、 CUI 専用のコードになっている

// 商品種類を表示する

public void display(){

for(int i=0;i<size;i++){

//

商品種類を表示

System.out.println(itemTypeArray[i].getId()+":"+itemTypeArray[i].getName()+":"

+itemTypeArray[i].getPrice()+"

円 ");

} }

ItemStock

クラスも同様

例題

11-1

(ItemTypeList.java)

#display()

(44)

display() メソッド

CUI と GUI では異なる表示にしたい

現状の

display()

メソッドでは

GUI

に対応 できない

Model

は構造だけに責任をもつ

1001:cola:120

1002:soda:120

CUI

商品種類表示

GUI

商品種類表示

(45)

④ display() メソッドの廃止

表示の責任は View が持つべきだか ら、 display() メソッドは廃止する

変わりに CUI 、 GUI がそれぞれの表示 をできるようにメソッドを追加する

int size()

要素数を取得する

ItemType get(int index)

index

番目の商品種類を取得する

(46)

display() は View に任せる

// 商品種類リストを閲覧する

public void showItemTypeList(){

itemTypeList.display();

}

// 商品種類リストを閲覧する

public void showItemTypeList(){

int len = itemTypeList.size();

for(int i=0;i<len;i++){

ItemType itemType = itemTypeList.get(i);

System.out.println(itemType.getId()+":"

+itemType.getName()+":"

+itemType.getPrice()+"

円 ");

} }

size()

メソッドと

get(index)

メソッド があれば、表示可能

例題

11-2

(CUIAdminApp.java)

# showItemTypeList()

(47)

Model-View 分離

Model と View で責任を分離したプログ ラムの利点

表示の変更が容易に行える

様々な表示(

CUI,GUI

)に対応した

Model

プログラムが書ける

重複コードがなくなる

(48)

14.3.3

GUI 自動販売機プログラミン グ

① 自動販売機用コンポーネント

② GUI 自動販売機の起動

③ UserFrame 解説

④ 100 円投入ボタンを追加する

(49)

① 自動販売機用コンポーネント (1)

BackgroundPanel

クラス

背景用のコンポーネントです。

この上に他の自販機コンポーネントを乗せる ことができます。

ItemImagePanel

クラス

商品種類を表示するための コンポーネントです。

代表的なクラス

(50)

① 自動販売機用コンポーネント (2)

BuyButton

クラス 購入ボタンです

ProductOutlet

クラス 商品取り出し口です

CoinDeposit

クラス

投入金額を表示します

(51)

② GUI 自動販売機の起動

//GUI

自動販売機を起動するためのメイン・クラス

public class Example14_6 {

/**

*

プログラム・メイン

* 操作するための 2 つのウインドウ(管理ウインドウ , 購入ウインドウ)

* を生成、表示する

*/ public static void main(String args[]){

ItemTypeList itemTypeList = new ItemTypeList(); //

商品種類リストを生成

Account account = new Account(); //

投入金勘定を生成

//

管理ウインドウを生成して表示する

AdminFrame adminFrame = new AdminFrame(itemTypeList,account);// 生成 adminFrame.setVisible(true);// 表示

// 購入ウインドウを生成して表示する

UserFrame userFrame = new UserFrame(itemTypeList,account);//

生成 userFrame.setVisible(true);// 表示

}

itemTypeList

Account

を生成して

2

つのウインドウに渡している

例題

14-6

(Example14_6.java)

(52)

③ UserFrame 解説

コンストラクタ

各種コンポーネントを生成して、ウインド ウに貼り付ける

更新メソッド (3 種類 )

Model

の状態を反映して、表示を更新するた

めに使う

イベント・ハンドラ

ボタンが押された時のイベントハンドラを 記述

例題

14-6 (UserFeame.java)

(53)

④ 100 円投入ボタンを追加す る

100 円投入できるようにする

ボタンが押されたら

(54)

100 円投入ボタンを追加する

//ユーザフレーム(商品購入メインウインドウ)クラス // 説明に不要な部分を割愛してある

public class UserFrame extends JFrame{

public JButton button100 = new JButton();//100円ボタン // コンストラクタ

public UserFrame(ItemTypeList newItemTypeList,Account newAccount){

//100円投入ボタン設定

button100.setText("100円");

button100.setBounds(new Rectangle(385, 240, 79, 27));

button100.addActionListener(new Button100_ActionListener());

background.add(button100, null);

}

//100円投入ボタン・イベントハンドラ

class Button100_ActionListener implements java.awt.event.ActionListener{

public void actionPerformed(ActionEvent e) { account.insert(new Money(100));//100円投入する stateUpdate();//状態を更新する

} }

ボタン生成

ボタン設定

イベント・ハンドラ

例題

14-7 (UserFeame.java)

(55)

イベント・ハンドラ解説

//100

円投入ボタン・イベントハンドラ

class Button100_ActionListener implements java.awt.event.ActionListener{

public void actionPerformed(ActionEvent e) { account.insert(new Money(100));//100

円投入する stateUpdate();// 状態を更新する

} }

投入金勘定への金の追加

CUI

と同様

stateUpdate()

を呼ぶ

構造が変化したら

stateUpdate()

を呼ぶと表示が更新される

(56)

課題ヒント

課題 14-3: 購入ボタンのイベント・ハン ドラを実装せよ

// ユーザフレーム(商品購入メインウインドウ)クラス // 購入ボタンのイベントハンドラ以外は割愛

public class ShoppingFrame extends JFrame{

//

購入ボタン・イベントハンドラ

// 押されたボタンと、そのボタンが対象とする商品の種類が引数

public void buyButton_pressed(BuyButton buyButton,ItemType itemType){

}

}

購入ボタン用のイベントハンドラが用意されている

(57)

//

購入ボタン・イベントハンドラ

// 押されたボタンと、そのボタンが対象とする商品の種類が引数

public void buyButton_pressed(BuyButton buyButton,ItemType itemType){

//

買えるかどうか確認する // 在庫の確認をする

//

投入されている金が価格より高いか確認をする

//

購入する

  // 保管庫から商品を取り出す

productOutlet.addItem(item); //

取り出し口に出す

//

おつりをだす

System.out.println("

おつりは~~円です "); // おつりの表示

//

投入金勘定をリセットする

stateUpdate();// 状態を更新する

}

購入イベント・ハンドラの実装

プログラムの目的(コメント)は、

CUI

プログラムと同様にな る

コメントに合わせてプログラムを書く

構造が変化したら、状態を更新する

取り出し口に出すプログラム

item

は取り出した商品

参照

関連したドキュメント

留学生 して人間形成されていると感じて 歴史都市・金沢にある大学ならで 積極的に関わろうとする姿に感

This paper presents a case of material and classroom guideline design to motivate autonomous learning of kanji and vocabulary in advanced Japanese language classes. The main goal

( 「時の法令」第 1592 号 1999 年 4 月 30 日号、一部変更)として、 「インフォームド・コンセ ント」という概念が導入された。同時にまた第 1 章第

本時は、「どのクラスが一番、テスト前の学習を頑張ったか」という課題を解決する際、その判断の根

日本語で書かれた解説がほとんどないので , 専門用 語の訳出を独自に試みた ( たとえば variety を「多様クラス」と訳したり , subdirect

第1回 平成27年6月11日 第2回 平成28年4月26日 第3回 平成28年6月24日 第4回 平成28年8月29日

回答した事業者の所有する全事業所の、(平成 27 年度の排出実績が継続する と仮定した)クレジット保有推定量を合算 (万t -CO2

また、特 特定 定切 切盛 盛土 土を を行 行う う場 場合 合に には は、 、一 一般 般承 承継