トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

2012夏季集中講義GUI

概要 2012年度夏 Java Swing によるGUI

Swing によるGUI作成法を5コマ集中で速習する。本授業と実行環境が少し異なるが、内容的にはJava2005に完全に準拠する。より厳密で詳細な説明がほしい人は、そちらを参照してほしい。

第2回以降は別ページへ

  第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);
    }
}