教育サーバーのページ
オンラインテキスト目次
ソフトウエア基礎演習
SwingはAWTの後継として1997年にリリースされた。 基本的な部分はAWTの機能を踏襲して作成されているが、 GUI部品の外見を実行時に変更できたり、多機能などの利点がある。
SwingのGUI部品には、以下のような特徴がある。
100% ピュアJavaであるSwingは全部Javaで記述されている。 それゆえに、クロスプラットホームを実現していると言える。 従来のAWTのGUI部品を使って書いたJavaプログラムは、 動作としてはどのOS上でも同じであったが、 「見かけ(ルック&フィール)」はOSごとにそれぞれ異なっていた。 SwingのGUI部品を使えば,動作だけでなく、 見かけも含めて統一可能である。
実行時にルック&フィールを切り替え可能であるルック&フィールを統一できるだけではなく、 複数のルック&フィールを用意しておいて、 実行時に切り替えることができる。 この機能は「着脱可能な」(Pluggable)ルック&フィールと呼ばれる。
きめ細かい設定やカスタマイズが可能AWTのGUI部品では、ボタンなどにはテキストしか表示できないが、 Swingではテキスト以外にも、比較的簡単に画像ファイルを貼り付けたり、 自分でグラフィックスを描画したりできる。 また、クラスライブラリは、 こうした柔軟な処理を体系的に行なえるような構成になっている。
以下、Swingを使ったGUIプログラミングについて解説するが、 SwingはAWTの全ての機能を置き変えたものではなく、 多くはAWTの機能をそのまま利用する。 このため、Swingを使うにはAWTを使う知識も必要になる。
SwingによりGUIアプリケーションを作成する場合、 ボタンやラベル、メニューなどのGUI部品を自由に組み合わせる。 そのために、GUI部品を入れるための「器」を用意することが必要となり、 これをコンテナとよぶ。
Swingによりアプリケーションを作成する場合には、 土台となるコンテナには、JFrameクラスを利用することが一般的である。 JFrameは、Swingパッケージに含まれるクラスの一つであり、 アプリケーションのウィンドウを作るために利用されるクラスである。
JFrameクラスを使ったGUIアプリケーション作成の流れは以下のようになる。
次のプログラム MyWinApp.java
はフレームというウィンドウをベースとした普通のウィンドウを表示するプログラムである。
このプログラムを実行することで表示されるウィンドウは、
見た目は普通のウィンドウであるので、
その右上の終了ボタンで終了できそうだが、
実際には終了することはできない。
これを終了するためには、
Ctrl+Cなどで強制終了させる必要がある。
import java.awt.*; import javax.swing.*; public class MyWinApp { public static void main(String[] args) { JFrame f = new JFrame(); f.setSize(300, 200); f.setVisible(true); } }
実行例は、たとえば次のようになる。
% java MyWinApp ... .... ウィンドウシステムを強制終了させる場合には、コマンドプロンプトウィンドウ上でCtrl+Cを入力する。プログラムの説明
プログラム前半の
JFrame f = new JFrame();
では、新しいフレーム(基本的なウィンドウ(JFrame))オブジェクトを作成している。
f.setSize(300, 200);
では、ウィンドウの横幅を300、高さを200に設定している。
f.setVisible(true);
は、ウィンドウの表示命令を示している。
次のプログラム MyWinApp1.java
はフレームというウィンドウをベースとした普通のウィンドウを表示するプログラムである。
このプログラムを実行することで表示されるウィンドウは、
その右上にある終了ボタンで終了できる。
import java.awt.*; import java.awt.event.*; import javax.swing.*; class MyFrame extends JFrame { public MyFrame() { setSize(300, 200); addWindowListener(new MyWindowAdapter()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyWinApp1 { public static void main(String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } }
ウィンドウのクローズボタンをクリックすることで、 ウィンドウシステムを正常に終了させることができる
プログラムの説明プログラム前半の
class MyFrame extends JFrame
では、新しいフレームクラスMyFrameをJFrameクラスを継承して定義している。
addWindowListner(new MyWindowAdapter());
では、イベントソースであるウィンドウシステムとイベントリスナであるMyWindowAdapterとを関連付けている。 これによって、WindowEventを受け取るイベントリスナを指定している。 つまり、イベントソースであるウィンドウのクローズボタンをクリックしたときには、 ウィンドウクローズを通知するイベントがイベントリスナに伝えられる。 アプリケーションはそのイベントリスナで定義されているメソッド windowClosing(WindowEvent e)を起動し、終了処理を行う。
class MyWindowAdapter extends WindowAdapter
では、イベントリスナーである MyWindowAdapterクラスはWindowAdapterクラスを継承して作成されている。
public void windowClosing(WindowEvent e){ System.exit(0);}
では、プログラムを正常終了するための処理が記述されている。
次のプログラム MyWinApp1n.java
は、上記のMyWinApp1n.java
に対してさらに、
タイトルを表示できるようにしたプログラムである。
import java.awt.*; import java.awt.event.*; import javax.swing.*; class MyFrame extends JFrame { public MyFrame() { setTitle("My Window Application"); setSize(300, 200); addWindowListener(new MyWindowAdapter()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyWinApp1n { public static void main(String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } }プログラムの説明
プログラム前半の
setTitle("My Window Application");
では、フレームにタイトルを表示している。
GUIアプリケーションの構築では、アプリケーションの土台となる「入れ物」 (コンテナ)の中に必要なGUI部品を組み込んでいく。
通常、コンテナとなるGUI部品には他のGUI部品を組み込むことができるが、 今回利用したJFrameクラス(JDialog, Jwindow, JAppletも)では、 コンテナに直接GUI部品を組み込むことはできない。 ここでは、GUI部品の追加は、 コンテナから取得したcontentPaneに対しておこなう。
GUIアプリケーションを作成する際に、 重要なことはGUI部品をコンテナ上にうまくレイアウト(配置)して、 使いやすいユーザインターフェイスとすることが必要である。 Swingを利用したGUIアプリケーションでは、 GUI部品を配置する場合、レイアウトマネージャを使用する。
次のプログラム MyButtonTest.java
は、
GUIでよく使われるコンポーネントであるボタンが配置されたウィンドウを表示できるようにしたプログラムである。
import java.awt.*; import java.awt.event.*; import javax.swing.*; class MyFrame extends JFrame { JButton b1; public MyFrame(){ Container contentPane = getContentPane(); setTitle("My Button Application"); setSize(300, 200); contentPane.setLayout(new FlowLayout()); b1 = new JButton("Button1"); contentPane.add(b1); addWindowListener(new MyWindowAdapter()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyButtonTest { public static void main(String[] args) { MyFrame f = new MyFrame(); // f.show(); f.setVisible(true); } }プログラムの説明
プログラム前半の
Container contentPane = getContentPane();
では、JFrameオブジェクトからコンテントペインと呼ばれるコンテナを取得することを示す。
プログラム前半の
content.Pane.setLayout(new FlowLayout());
では、FlowLayoutレイアウトマネージャのインスタンスを生成し、 作成したレイアウトのインスタンスをコンテナにセットすることで、 左から右方向にボタンを配置することを示す。
b1 = new JButton("Button1");
では、"Button1"というラベルのボタンオブジェクトを生成することを示す。
contentPane.add(b1);
では、生成されたボタンオブジェクトをコンテナオブジェクトに追加することを示す。
次のプログラム MyButtonTest1s.java
は、
GUIでよく使われるコンポーネントであるボタンが配置されたウィンドウを表示できるようにしたプログラムである。
import java.awt.*; import java.awt.event.*; import javax.swing.*; class MyFrame extends JFrame { JButton b1, b2, b3; public MyFrame(){ Container contentPane = getContentPane(); setTitle("My Button Application"); setSize(300, 200); contentPane.setLayout(new FlowLayout()); b1 = new JButton("Button1"); contentPane.add(b1); b2 = new JButton("Button2"); contentPane.add(b2); b3 = new JButton("Button3"); contentPane.add(b3); addWindowListener(new MyWindowAdapter()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyButtonTest1s { public static void main(String[] args) { MyFrame f = new MyFrame(); // f.show(); f.setVisible(true); } }プログラムの説明
b1 = new JButton("Button1"); b2 = new JButton("Button2"); b3 = new JButton("Button3");
では、"Button1"、"Button2"、"Button3"という3つのラベルのボタンオブジェクトを生成することを示す。
contentPane.add(b1); contentPane.add(b2); contentPane.add(b3);
では、生成された3つのボタンオブジェクトをコンテナオブジェクトに追加することを示す。
Swingにおいてイベントの扱いは、AWTと同様である。 イベントソースでイベントが発生するとあらかじめ登録しておいた イベントリスナーに定義されているメソッドを実行する。
イベント処理を実装する場合には、以下のような手続きを実行することになる。
次のプログラム MyButtonTest2n.java
は、ボタンが押されたことに対してイベント処理を施したプログラムである。
import java.awt.*; import java.awt.event.*; import javax.swing.*; class ButtonTestFrame extends JFrame implements ActionListener { JButton b1, b2, b3; public ButtonTestFrame() { Container contentPane = getContentPane(); setTitle("My Button Application"); setSize(300, 200); addWindowListener(new MyWindowAdapter()); contentPane.setLayout(new FlowLayout()); b1 = new JButton("Button1"); b2 = new JButton("Button2"); b3 = new JButton("Button3"); b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); contentPane.add(b1); contentPane.add(b2); contentPane.add(b3); } public void actionPerformed(ActionEvent ae){ if (ae.getSource() == b1) System.out.println("Button1がクリックされました"); else if (ae.getSource() == b2) System.out.println("Button2がクリックされました"); else if (ae.getSource() == b3) System.out.println("Button3がクリックされました"); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MyButtonTest2n { public static void main(String[] args) { ButtonTestFrame f = new ButtonTestFrame(); // f.show(); f.setVisible(true); } }プログラムの説明
このプログラムのイベント処理では、 イベントソースであるJButtonクラスから発生したイベントを、 イベントリスナであるButtonTestFrameクラスとMyWindowAdapterクラスに伝達することで処理がおこなわれる。
class ButtonTestFrame extends JFrame implements ActionListner
では、ボタンが押されたというイベントを受け付け、 それに対する処理を実行するために、 ButtonTestFrameクラスがActionListnerインタフェースを実装していることを表す。
public void actionPerformed(ActionEvent ae){ if (ae.getSource() == b1) System.out.println("Button1がクリックされました"); else if (ae.getSource() == b2) System.out.println("Button2がクリックされました"); else if (ae.getSource() == b3) System.out.println("Button3がクリックされました"); }
は、ActionListnerインタフェースにおいて実装されねばならないメソッドであり、 ボタンが押された際に実行される処理が記述されている。 この場合には、ボタンが押された場合には、"Button がクリックされました" という文字列が標準出力に表示されことを示している。 actionPerformed()メソッドの引数aeにはボタンがクリックされたイベント情報が入っている。 このオブジェクトaeはボタンがクリックされてときに生成される。 getSource()メソッドはイベントソースを見つけるために利用する。
b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this);
では、ボタンに対してイベントリスナーを登録している。 これによって、ボタンをクリックされたことにより発生するイベントを感知してactionPerformed()メソッドを呼び出すことができるようになる。
class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }
では、リスナーインターフェイスを実装しないで、 WindowAdapterを継承したMyWindowAdapterを定義している。
AWTで説明したテキストフィールド、チェックボックスなどのコンポーネントは、 SwingではAWTのクラス名の先頭にJを付けたクラス名で用意されている。 以下の表を見よ。
種類 AWTのクラス名 Swingのクラス名 備考 フレーム Frame JFrame アプレット Applet JApplet ボタン Button JButton ラベル Label JLabel テキストフィールド TextField JTextField チェックボックス Checkbox JCheckBox JCheckBoxとBが大文字になっていることに注意! ラジオボタン Checkbox,
CheckboxGroupJRadioButton,
ButtonGroup大幅に異なる(下記参照) テキストエリア TextArea JTextArea
ただし、ラジオボタンだけは異なっている。以下の SwingRadioButtonTest.javaは、 Swingでラジオボタンを実現する例である。
import javax.swing.*; import java.awt.*; import java.awt.event.*; class MyFrame extends JFrame implements ActionListener { JButton b1; ButtonGroup g; JRadioButton rb1, rb2, rb3; public MyFrame() { Container contentPane = getContentPane(); setSize(300,200); addWindowListener(new MyWindowAdapter()); contentPane.setLayout(new FlowLayout()); g = new ButtonGroup(); rb1 = new JRadioButton("1", false); g.add(rb1); contentPane.add(rb1); rb2 = new JRadioButton("2", false); g.add(rb2); contentPane.add(rb2); rb3 = new JRadioButton("3", false); g.add(rb3); contentPane.add(rb3); b1 = new JButton("Push"); contentPane.add(b1); b1.addActionListener(this); } public void actionPerformed(ActionEvent ae) { // JRadioButtonの現在の値を標準出力に表示する System.out.println("radiobutton1 is " + rb1.isSelected()); System.out.println("radiobutton2 is " + rb2.isSelected()); System.out.println("radiobutton3 is " + rb3.isSelected()); } } class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MySwingRadioButtonTest { public static void main(String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } }
AWTでは、Checkboxクラスを使用したが、Swingでは JRadioButtonを使う。 また、いくつかのラジオボタンをまとめるには、ButtonGroupを使う。 ラジオボタンをまとめる時は、ButtonGroupオブジェクトに対しaddメソッドを 使いラジオボタンを追加する。また、ラジオボタンが選択されているかどうかを 調べるメソッドはAWTでは getStateだったが、SwingではisSelectedとなる。 これは、チェックボックス(JCheckBox)でも同様である。
上のプログラム MyWinApp1.java
を書いて実行してみよ。さらに、ウィンドウサイズを480 x 300に変えて実行してみよ。
上のプログラム MyButtonTest.java
を書いて実行してみよ。さらに、GUI部品であるボタンの名前を「ボタン」に変えて実行してみよ。
上のプログラム MyButtonTest1s.java
を書いて実行してみよ。さらに、GUI部品である4つのボタンを2X2の格子上に配置して表示してみよ。この場合には、setLayout(new FlowLayout());の代わりにsetLayout(new GridLayout(2,2));を使うこと。
MyButtonTest.java
をボタンを押すと、ボタンに書かれた文字が"Pressed"に変わるように
プログラムを修正せよ。ボタンに書かれた文字を変更するメソッドは、
API仕様などで調べよ。
Swingのルック&フィールの特徴を確認するために、上のプログラム
MyButtonTest1s.java
(Swing版)と、
AWTの説明にあった、MyButtonTest1.java
(AWT版)をそれぞれ、
WindowsとLinux上で実行せよ。そして、違いを説明せよ。
AWTのテキストフィールドを使う例であるMyTextFieldTest.java
をSwingを使うように書き変えよ。
AWTのチェックボックスを使う例であるMyCheckboxTest.java
をSwingを使うように書き変えよ。
AWTのテキストエリアを使う例であるMyTextAreaTest.java
をSwingを使うように書き変えよ。