概要 2012年度夏 Java Swing によるGUI
Swing によるGUI作成法を5コマ集中で速習する。本授業と実行環境が少し異なるが、内容的にはJava2005に完全に準拠する。より厳密で詳細な説明がほしい人は、そちらを参照してほしい。
第2回以降は別ページへ
- 第2回 イベント委譲モデル (delegation event model
- 第3回 独自の部品の作成(custom component)
- 第4回 ビットマップエディタの設計
- 第5回 ビットマップエディタの実装
第1回 入れ物(Container)、部品(Component)、オブジェクト間の配線(wiring)
Eclipse環境で新規もしくは既存のJavaプロジェクトを使用する。以下、この集中講義ではパッケージguiを作成し演習を勧める。
JFrame で外枠を用意する
以下のプログラムを実行し、コメントにある通りの動作が起きるか確認する。
package gui; import javax.swing.JFrame; public class FrameViewer { public static void main(String[] args) { // ウィンドウを表すインスタンスを作る (引数はタイトル) JFrame frame = new JFrame("フレームのテスト"); // 終了ボタンが押されたときの動作を決める (ウィンドウを処分する) frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // ウィンドウの大きさを決める (400x300) frame.setSize(400, 300); // ウィンドウを表示する frame.setVisible(true); } }
部品をJFrameのクライアント領域(contentPane)に貼りつける
ウィンドウ(JFrame)は3つの部分からなっている。
- タイトルバー
- ウィンドウ境界
- クライアントエリア(contentPane)
package gui; import javax.swing.JFrame; import javax.swing.JLabel; public class HelloSwing { public static void main(String[] args) { JFrame frame = new JFrame("文字表示のテスト"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // ウィンドウの ContentPane にラベルを追加する JLabel label = new JLabel("Hello, world!"); frame.getContentPane().add(label); // ウィンドウを表示する frame.setVisible(true); } }
必要なメソッド呼び出しをまとめておく。
JLabel でテキストをcentering
- Centering なら JLabel.CENTER
- Left justify なら JLabel.LEFT
- Right justify なら JLabel.RIGHT
package gui; import javax.swing.JFrame; import javax.swing.JLabel; public class CenteringHelloSwing { public static void main(String[] args) { JFrame frame = new JFrame("文字表示のテスト (2)"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // ウィンドウの ContentPane にラベルを追加する JLabel label = new JLabel("Hello, world!"); // - 文字を表示する位置を CENTER に設定する label.setHorizontalAlignment(JLabel.CENTER); frame.getContentPane().add(label); // ウィンドウを表示する frame.setVisible(true); } }
JLabel に画像を表示
- duke.gif の置き場所は、仮にUドライブのrootディレクトリとしたが、実際の位置に書き換えなければならない。
- Security の警告が出たときは「許可」を与えてよい。
package gui; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; public class ImageLabel { public static void main(String[] args) { JFrame frame = new JFrame("画像表示のテスト"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // 画像を取り込んでアイコンにする ImageIcon icon = new ImageIcon("U:/duke.gif"); // アイコンを表示するラベルを作成する JLabel label = new JLabel(icon); // ウィンドウの ContentPane にラベルを追加する frame.getContentPane().add(label); // ウィンドウを表示する frame.setVisible(true); } }
ボタン(JButton)を貼りつける
でもまだ action の設定はお預け。クリックしたとき少し様子が変わるあたりを確認せよ。
package gui; import javax.swing.JButton; import javax.swing.JFrame; public class ButtonViewer { public static void main(String[] args) { JFrame frame = new JFrame("ボタン表示のテスト"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // ウィンドウの ContentPane にボタンを追加する JButton button = new JButton("click"); frame.getContentPane().add(button); // ウィンドウを表示する frame.setVisible(true); } }
ボタンにactionを設定する
次のようなActionオブジェクトを生成して、ボタンの生成時にコンストラクタに渡すのが一手。
package gui; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; public class HelloAction extends AbstractAction { // 親クラス (AbstractAction) のコンストラクタに // アクションの名前 (String name) を渡すためのコンストラクタ public HelloAction(String name) { super(name); } // ボタンが押された際の処理を // actionPerformed(java.awt.event.ActionEvent) に記述する public void actionPerformed(ActionEvent e) { // ボタンが押された際に "Hello, world!" とコンソールに表示する System.out.println("Hello, world!"); } }
package gui; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; public class HelloButton { public static void main(String[] args) { JFrame frame = new JFrame("アクション付きボタンのテスト"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // HelloAction のインスタンス (アクションの実態) を作成 // コンストラクタにはボタンに表示する文字列を置く HelloAction action = new HelloAction("click->hello"); // ボタンを作成する際にアクションを渡す JButton button = new JButton(action); frame.getContentPane().add(button); // ウィンドウを表示する frame.setVisible(true); } }
Layout manager 東西南北に配置する
BorderLayoutを使ってみると
package gui; import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; public class DirectionViewer { public static void main(String[] args) { JFrame frame = new JFrame("BorderLayout のテスト"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // LayoutManager を BorderLayout にする frame.getContentPane().setLayout(new BorderLayout()); // add メソッド呼び出し時に、配置する位置も引数として渡す frame.getContentPane().add(new JButton("北"), BorderLayout.NORTH); frame.getContentPane().add(new JButton("南"), BorderLayout.SOUTH); frame.getContentPane().add(new JButton("東"), BorderLayout.EAST); frame.getContentPane().add(new JButton("西"), BorderLayout.WEST); frame.getContentPane().add(new JButton("中央"), BorderLayout.CENTER); // ウィンドウを表示する frame.setVisible(true); } }
必ずしも5分割でなくてよい。
package gui; import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; public class BorderViewer { public static void main(String[] args) { JFrame frame = new JFrame("レイアウトのテスト"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // レイアウトを java.awt.BorderLayout に設定 frame.getContentPane().setLayout(new BorderLayout()); // 中央 (ウィンドウ中央) にラベルを表示 frame.getContentPane().add(new JLabel("中央のラベル"), BorderLayout.CENTER); // 南 (ウィンドウ下部) にボタンを表示 frame.getContentPane().add(new JButton("南のボタン"), BorderLayout.SOUTH); // ウィンドウを表示する frame.setVisible(true); } }
格子状に配置する GridLayout
3行2列の例
package gui; import java.awt.GridLayout; import javax.swing.JButton; import javax.swing.JFrame; public class GridViewer { public static void main(String[] args) { JFrame frame = new JFrame("GridLayout のテスト"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // レイアウトを java.awt.GridLayout に設定 // -> new GridLayout(行数=3, 列数=2) frame.getContentPane().setLayout(new GridLayout(3, 2)); // ウィンドウにボタンを 6 個追加する frame.getContentPane().add(new JButton("1")); frame.getContentPane().add(new JButton("2")); frame.getContentPane().add(new JButton("3")); frame.getContentPane().add(new JButton("4")); frame.getContentPane().add(new JButton("5")); frame.getContentPane().add(new JButton("6")); // ウィンドウを表示する frame.setVisible(true); } }
複雑なレイアウトをつくる
- 入れ子のレイアウト
- 入れ子の概念図
package gui; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class CenterGrid { public static void main(String[] args) { JFrame frame = new JFrame("複雑なレイアウトのテスト"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(400, 300); // ContentPane のレイアウトを java.awt.BorderLayout に設定 frame.getContentPane().setLayout(new BorderLayout()); // 南 (ウィンドウ下部) にボタンを表示 frame.getContentPane().add(new JButton("南のボタン"), BorderLayout.SOUTH); // 中央 (ウィンドウ中央) に貼り付けるパネル JPanel centerPanel = new JPanel(); // パネルを GridLayout(行数=1, 列数=2) に設定 centerPanel.setLayout(new GridLayout(1, 2)); // パネルにボタンを二つ追加 centerPanel.add(new JButton("中央-左のボタン")); centerPanel.add(new JButton("中央-右のボタン")); // 中央 (ウィンドウ中央) にボタンが二つ貼りついたパネルを表示 frame.getContentPane().add(centerPanel, BorderLayout.CENTER); // ウィンドウを表示する frame.setVisible(true); } }
Text Field を貼りつける
package gui; import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JTextField; public class TextFieldViewer { public static void main(String[] args) { JFrame frame = new JFrame("テキストフィールド"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // レイアウトを java.awt.BorderLayout に設定 frame.getContentPane().setLayout(new BorderLayout()); // 中央 (ウィンドウ中央) にテキストフィールドを表示 frame.getContentPane().add(new JTextField("テキストフィールド"), BorderLayout.CENTER); // 東 (ウィンドウ右部) にボタンを表示 frame.getContentPane().add(new JButton("ボタン"), BorderLayout.EAST); // pack() メソッドは、サイズを自動的に調整してくれる frame.pack(); frame.setVisible(true); } }
Action オブジェクトを加えて配線を行う。
- 起動すると
- 「ほげ」と入力してボタンを押すと
{{ref_image echolabel-hoge.png}}
- Actionオブジェクトは以下の通り。
package gui; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JLabel; import javax.swing.JTextField; public class TextFieldAction extends AbstractAction { private final JTextField textField; private final JLabel label; public TextFieldAction(String name, JTextField field, JLabel label) { super(name); this.textField = field; this.label = label; } // ボタンが押されたらテキストフィールドの内容をラベルに貼り付ける public void actionPerformed(ActionEvent e) { // テキストフィールドからラベルへ String text = this.textField.getText(); this.label.setText(text); // テキストフィールドの内容を変更する this.textField.setText("clicked"); } }
- これを使うには以下のようなプログラムを走らせればよい。
package gui; import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; public class EchoLabel { public static void main(String[] args) { JFrame frame = new JFrame("ラベルの操作"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // レイアウトを java.awt.BorderLayout に設定 frame.getContentPane().setLayout(new BorderLayout()); // テキストフィールドを作成 JTextField tf = new JTextField("テキストフィールド"); // ラベルを作成 JLabel label = new JLabel("ラベル"); // ボタンを作成。ただし、アクションに TextFieldAction を設定する JButton button = new JButton(new TextFieldAction("ボタン", tf, label)); // テキストフィールドとボタンを貼り付けたパネルを作成 JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); panel.add(tf, BorderLayout.CENTER); panel.add(button, BorderLayout.EAST); // 中央 (ウィンドウ中央) にラベルを表示 frame.getContentPane().add(label, BorderLayout.CENTER); // 南 (ウィンドウ下部) にボタンを表示 frame.getContentPane().add(panel, BorderLayout.SOUTH); // ウィンドウを表示する frame.pack(); frame.setVisible(true); } }
centergrid.png
complexlayout.png
contentpane.png
directionviewer.png
duke.gif
echolabel-hoge.png
echolabel.png
gridviewer.png
textfieldaction.png
window.png