移転しました。

Swingでウインドウを表示する

TestFrame

小さなJavaアプリケーションを作るときのやり方を一つ。
人によってかなり差があるかもしれませんが。
一応、実行時の画像も載せます。
Endボタンで終了するだけで機能は全然ないです。


とりあえず先にコードを。


ソースコード

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TestFrame extends JFrame {

    private JPanel panel;

    private JLabel label;

    private JButton button;

    public TestFrame() {
        super("TestFrame");
        initComponents();
        initLayout();
        setSize(150,70);
        setResizable(false);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void initComponents() {
        panel = new JPanel();
        label = new JLabel("Hello World");
        button = new JButton("End");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                actionButton();
            }
        });
    }

    public void initLayout() {
        panel.setLayout(new BorderLayout());
        panel.add(label, BorderLayout.NORTH);
        panel.add(button, BorderLayout.CENTER);
        getContentPane().add(panel);
    }

    protected void actionButton() {
        System.exit(0);
    }

    public static void main(String[] args) {
        new TestFrame();
    }
}

私がいつもやるのはコンストラクタで、フレームやパネルのあるべき姿を作ることです。この例ではJFrameを継承してその持ち物に部品をフィールドとして持っています。このコードではフィールドにしなくてもよさそうですが、別のウインドウや処理から参照するアクセサメソッドが必要になると、このようにしている方が便利な場合が多いです。


コンストラク

    public TestFrame() {
        super("TestFrame");
        initComponents();
        initLayout();
        setSize(150,70);
        setResizable(false);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

この部分がコンストラクタですが、親コンストラクタを呼び出した後に、コンポーネントの生成、レイアウトの調整を行って、最後にフレーム自体のレイアウトや初期設定を行っています。


コンポーネント生成

    public void initComponents() {
        panel = new JPanel();
        label = new JLabel("Hello World");
        button = new JButton("End");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                actionButton();
            }
        });
    }

コンポーネント生成のメソッドですが、未だにpublicかprotectedかで悩みます。ヘルパメソッドをprivateにすることはあまりありませんが、フレームの初期化を他から実行するかどうかは一般的にはどちらが良いのでしょうか。
内容は生成と部品の初期化で必要な作業のレイアウト以外を行います。この場合はボタン押下のアクションを定義しています。


レイアウト調整

    public void initLayout() {
        panel.setLayout(new BorderLayout());
        panel.add(label, BorderLayout.NORTH);
        panel.add(button, BorderLayout.CENTER);
        getContentPane().add(panel);
    }

レイアウト作業です。この中身は時と場合によって大きく変化します。


アクションメソッド

    protected void actionButton() {
        System.exit(0);
    }

ここではイベントが一つしかないので直接処理を記述していますが、複数のアクションイベントがある場合はコントローラメソッドを作って分岐することもあります。

このようなイメージでフレームに外部で定義したJPanelの継承クラスなどを配置して作ってます。只、規模が大きくなるとレイアウトの調整などがまとまっていないとツライかなとも思いますが。


Swingは一つ一つがキレイなオブジェクトなので(勿論Javaのコアライブラリは遍くそう設計されていますが)同じ思想に乗っかるだけで簡単にオブジェクティブなコードを書くことができます。
今回はActionListenerを無名クラスにしているので少し手抜き感がありますが、これも必要であればクラスとして作っていくと、一つのクラスには一つの概念のみを定義すべきとのオブジェクト指向の考え方に則って作ることができて、スッキリしたコードで実現することができます。