プログラミング応⽤b第12回 -...
Transcript of プログラミング応⽤b第12回 -...
Web資料 : http://www.ohshiro.tuis.ac.jp/~ohshiro/progaa/村上クラス : http://www.edu.tuis.ac.jp/~ym206508/lecture/programming/
村上クラス令和元年12⽉11⽇
プログラミング応⽤b 第12回
GUIその3(AWT/Swingによるウィンドウのデザインと⽣成)
1. 引き続き,Java GUI のイベント処理について紹介していく2. 残った時間は,前回出題された15パズルの課題がまだ合格してい
ない場合は完成させる。合格した場合は改善改良を⾏う (パズルが解けたかどうかの判定を⼊れる等)。
本⽇の⽬標
メニューとイベント処理の例
メニューとイベント処理の例ActionListener リスナ で対処できる標準的なイベント処理の例として,Swing版メニューのイベント処理の例を紹介する。
• メニューが選択された時のイベントも,メニューの標準的なイベントとして, ActionListenerリスナ と actionPerformed( )メソッド のオーバライドで対応
• 例: ファイルメニューから"開く"または"閉じる"というメニュー項⽬を選択すると,各メニュー項⽬に応じたメッセージウィンドウが開く
※ GUIを制御するスレッドがメインスレッドとは別に⽣成・実⾏されるために、main( ) メソッドが処理を終了しても,ウィンドウは開いたままであり,メニュー処理も実⾏され続けている。
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;
class SwingMenuEventTest {public static void main( String args[ ]) {
final JFrame f = new JFrame( "Swing Men" );f.setSize( 200, 100 );
JMenu fileMenu = new JMenu( "ファイル" );
JMenuItem miOpen = new JMenuItem( "開く" );fileMenu.add( miOpen );
JMenuItem miClose = new JMenuItem( "閉じる" );fileMenu.add( miClose );
JMenuBar mbar = new JMenuBar();mbar.add( fileMenu );
miOpen.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {JOptionPane.showMessageDialog( f.getContentPane( ), "¥"開く¥"が選ばれた。" );
}}
);
miClose.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {JOptionPane.showMessageDialog( f.getContentPane( ), "¥"閉じる¥"が選ばれた。" );
}}
);
f.setJMenuBar( mbar );f.setVisible( true );
}}
SwingMenuEventTest.java
ウィンドウの作成※Java 8 (JDK1.8) でコンパイルする場合は final は要らない。
"ファイル"メニューの作成
メニュー項⽬"開く"の作成と"ファイル"メニューへの登録
メニュー項⽬"閉じる"の作成と"ファイル"メニューへの登録
メニューバーの作成とメニューの登録
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;
class SwingMenuEventTest {public static void main( String args[ ]) {
final JFrame f = new JFrame( "Swing Men" );f.setSize( 200, 100 );
JMenu fileMenu = new JMenu( "ファイル" );
JMenuItem miOpen = new JMenuItem( "開く" );fileMenu.add( miOpen );
JMenuItem miClose = new JMenuItem( "閉じる" );fileMenu.add( miClose );
JMenuBar mbar = new JMenuBar();mbar.add( fileMenu );
miOpen.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {JOptionPane.showMessageDialog( f.getContentPane( ), "¥"開く¥"が選ばれた。" );
}}
);
miClose.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {JOptionPane.showMessageDialog( f.getContentPane( ), "¥"閉じる¥"が選ばれた。" );
}}
);
f.setJMenuBar( mbar );f.setVisible( true );
}}
イベントリスナを”開く”メニューに登録するリスナクラスとして ActionListener の匿名サブクラス を定義し,actionPerformed()メソッド をオーバライドしている
イベントリスナを”閉じる”メニューに登録する
その場でオブジェクトを⽣成して,addActionListener( )メソッドへ実引数として渡すことによって,イベントリスナとして登録
SwingMenuEventTest.java
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;
class SwingMenuEventTest {public static void main( String args[ ]) {
final JFrame f = new JFrame( "Swing Men" );f.setSize( 200, 100 );
JMenu fileMenu = new JMenu( "ファイル" );
JMenuItem miOpen = new JMenuItem( "開く" );fileMenu.add( miOpen );
JMenuItem miClose = new JMenuItem( "閉じる" );fileMenu.add( miClose );
JMenuBar mbar = new JMenuBar();mbar.add( fileMenu );
miOpen.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {JOptionPane.showMessageDialog( f.getContentPane( ), "¥"開く¥"が選ばれた。" );
}}
);
miClose.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {JOptionPane.showMessageDialog( f.getContentPane( ), "¥"閉じる¥"が選ばれた。" );
}}
);
f.setJMenuBar( mbar );f.setVisible( true );
}}
JOptionPane.showMessageDialog()メソッド を利⽤して
簡単なメッセージ表⽰⽤のウィンドウを表⽰。このメソッドは,
第1引数 - 親ウインドウ (特に指定しなければ null でも良い)第2引数 - メッセージ⽂字列を渡す。
static メソッドなので,何かしらオブジェクトを⽣成する必要
も無く使⽤できるので⼿軽に利⽤できる。
SwingMenuEventTest.java
getContentPaneメソッドは、フレームのContentPaneを表す
Container型(java.awt.Container)オブジェクトを取得
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;
class SwingMenuEventTest {public static void main( String args[ ]) {
final JFrame f = new JFrame( "Swing Men" );f.setSize( 200, 100 );
JMenu fileMenu = new JMenu( "ファイル" );
JMenuItem miOpen = new JMenuItem( "開く" );fileMenu.add( miOpen );
JMenuItem miClose = new JMenuItem( "閉じる" );fileMenu.add( miClose );
JMenuBar mbar = new JMenuBar();mbar.add( fileMenu );
miOpen.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {JOptionPane.showMessageDialog( f.getContentPane( ), "¥"開く¥"が選ばれた。" );
}}
);
miClose.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {JOptionPane.showMessageDialog( f.getContentPane( ), "¥"閉じる¥"が選ばれた。" );
}}
);
f.setJMenuBar( mbar );f.setVisible( true );
}}
メニューバーをウィンドウに追加
ウィンドウを可視化する
SwingMenuEventTest.java
チェックボックスとイベント処理の例
チェックボックスとイベント処理の例Swing版チェックボックスのイベント処理の例を紹介する。
実⾏すると,2個のチェックボックスが配置されたウィンドウが表⽰され,それぞれのチェックボックスをクリックして選択・解除するごとに,コンソール出⼒にその内容が表⽰される。
前回紹介した表で,チェックボックスの選択を変化させたときに発⽣するイベントは ItemEvent 型オブジェクトで,対応するリスナは, ItemListener である。
⇨ 呼ばれるメソッドはitemStateChanged( )
import java.awt.Container;import java.awt.FlowLayout;import java.awt.event.ItemEvent;import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JCheckBox;import javax.swing.JFrame;
class MyApplication {JFrame f;JCheckBox jcb1, jcb2;
class MyItemListener implements ItemListener {public void itemStateChanged( ItemEvent e ) {String msg = "";
if( e.getItemSelectable() == jcb1 ) {if( jcb1.isSelected() ) { msg = "選択肢1が選択された"; }else { msg = "選択肢1の選択が解除された"; }
}if( e.getItemSelectable() == jcb2 ) {
if( jcb2.isSelected() ) { msg = "選択肢2が選択された"; }else { msg = "選択肢2の選択が解除された"; }
}
System.out.println( msg );}
}
SwingMenuEventTest.java
(続き)
public MyApplication( String str ) {f = new JFrame( str );f.setSize(350, 80);
Container c = f.getContentPane( );c.setLayout( new FlowLayout( ) );
jcb1 = new JCheckBox( "選択肢1" );
c.add( jcb1 );jcb1.addItemListener( new MyItemListener( ) );
jcb2 = new JCheckBox( "選択肢2" );
c.add( jcb2 );jcb2.addItemListener( new MyItemListener( ) );
f.addWindowListener(
new WindowAdapter( ) {public void windowClosing( WindowEvent e ) {System.exit( 0 );}
});f.setVisible( true );}}
class SwingCheckBoxTest {public static void main( String args[ ] ) {
MyApplication app
= new MyApplication( "チェックボックスの使用例" );}}
MyApplicationクラス のコンストラクタで、チェックボックスにリスナを登録している。
選択項⽬に ItemListener型のリスナオブジェクトを登録するには, addItemListener( ) メソッド を利⽤する。
import java.awt.Container;import java.awt.FlowLayout;import java.awt.event.ItemEvent;import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JCheckBox;import javax.swing.JFrame;
class MyApplication {JFrame f;JCheckBox jcb1, jcb2;
class MyItemListener implements ItemListener {public void itemStateChanged( ItemEvent e ) {String msg = "";
if( e.getItemSelectable() == jcb1 ) {if( jcb1.isSelected() ) { msg = "選択肢1が選択された"; }else { msg = "選択肢1の選択が解除された"; }
}if( e.getItemSelectable() == jcb2 ) {
if( jcb2.isSelected() ) { msg = "選択肢2が選択された"; }else { msg = "選択肢2の選択が解除された"; }
}
System.out.println( msg );}
}
SwingMenuEventTest.java
(続き)
public MyApplication( String str ) {f = new JFrame( str );f.setSize(350, 80);
Container c = f.getContentPane( );c.setLayout( new FlowLayout( ) );
jcb1 = new JCheckBox( "選択肢1" );
c.add( jcb1 );jcb1.addItemListener( new MyItemListener( ) );
jcb2 = new JCheckBox( "選択肢2" );
c.add( jcb2 );jcb2.addItemListener( new MyItemListener( ) );
f.addWindowListener(
new WindowAdapter( ) {public void windowClosing( WindowEvent e ) {System.exit( 0 );}
});f.setVisible( true );}}
class SwingCheckBoxTest {public static void main( String args[ ] ) {MyApplication app
= new MyApplication( "チェックボックスの使用例" );}}
リスナの実装クラスで, itemStateChanged( ) をオーバライド
ItemEvent型の getItemSelectable( ) メソッド は、イベントソースの選択項⽬オブジェクトを ItemSelectable型 で返す。
チェックボックスが選択されているかどうかはJCheckBoxがスーパークラスのスーパークラスAbstractButtonから継承した isSelected( ) メソッドを使って調べる事ができる。
前回紹介した継承・実装関係の図(中央やや左)を⾒ると分かるが,ItemSelectableは,「選択可能な項⽬」の性質を定めているインタフェイスで, JCheckBox も間接的にこのインタフェイスを実装している。
GUIプログラミングとスレッド
GUIプログラミングとスレッドクリティカルセクションに対して同期処理を施し,デッドロックなどもきっちり対処している事を,スレッドに対して安全である (スレッドセーフ) と⾔う。
Swing/AWTが提供するAPI は,実⾏効率が重視されていることもあって,スレッドに対して完全に安全ではない (部分的にはスレッドセーフとされる箇所もあるが,全体的にはスレッドセーフではない)
JavaではGUIコンポーネントの描写などを複数の別個のスレッドから同時並⾏的に実⾏すると,競合が起こってしまう可能性があるため,マルチスレッド機能を利⽤しているプログラムでは,Swingの描写処理を特定の⼀つのスレッドに任せる仕組みが⽤意されている。
ここでは詳しくは解説しないが,Javaでマルチスレッドを活⽤したGUIプログラムを作成する際は,この事を思い出して,やり⽅を調べてみて欲しい。
• JavaのGUIの基本的な使い⽅を習得すれば,Javaによるプログラミングも幅が広がる。
• 紹介できなかったGUI機能についても,是⾮,積極的に調べて活⽤してみよう。