1
4

More than 3 years have passed since last update.

【Java発展学習17日目】SwingによるウィンドウUI制御

Last updated at Posted at 2021-07-22

GUIの種類

GUI(Graphical User Interface)の実現方法は、以下の2通り。

GUI 用途 デザイン設計
WebUI Webアプリケーション HTML
ウィンドウUI OSアプリケーション プログラム

Swing APIにおける3つのウィンドウ

参考: Swing
Swing APIが扱うウィンドウは、以下の3種類に分類される。

ウィンドウ 内容 API
アプレット ブラウザへの埋め込みウィンドウ JApplet
フレーム アプリケーション用ウィンドウ JFrame
ダイアログ 対話入力用ウィンドウ JDialog

また、これらのウィンドウはメインスレッドとは独立した、描画処理を行うUIスレッドによって実行される。
UIスレッドは複数のスレッドの総称であり、中でもイベントハンドラが動作するスレッドを
イベントディスパッチスレッド(EDT; event dispatch thread)と呼ぶ。

ただし、イベントハンドラによる処理負荷が大きい場合は、イベントディスパッチスレッドとは異なるスレッドで
負荷の大きい処理を行うSwingUtilities.invokeLater()メソッドを先に呼び出し、処理を進めておく手法を用いる。

SwingUtilities.invokeLater()

invokeLater()メソッド
void SwingUtilities.invokeLater(Runnable doRun)
// パラメータ
// doRun: 処理(タスク)を定義する、「Runnableインタフェースの実装クラスオブジェクト」または「関数オブジェクト」

Swing APIにおける7つのレイアウトマネージャ

参考・出典: A Visual Guide to Layout Managers
画面サイズやウィジェットに応じて自動レイアウトを行うレイアウトマネージャは、以下の7つ。

JFrame#setLayout()メソッドで利用するレイアウトマネージャを指定することができ、
デフォルトレイアウトとしてBorderLayoutが設定されている。

レイアウトマネージャ 配置 イメージ図
BorderLayout 上下左右・中央の5箇所 BorderLayout.png
BoxLayout 縦または横一列 BoxLayout.png
CardLayout ウィジェットに応じた動的レイアウト CardLayout.png CardLayout-2.png
FlowLayout 折り返し可能な横一列 FlowLayout.png
GridBagLayout 自由サイズのセル分割 GridBagLayout.png
GridLayout 固定サイズのセル分割 GridLayout.png
GroupLayout 縦横のグループ配置 GroupLayout.png
SpringLayout 比率分割 SpringLayout.png SpringLayout-2.png

フレームの生成

フレームは、JFrameクラスで定義される。
また、JPanelクラスで定義されるパネルを用いて、フレーム内にレイアウトをネストすることができる。

サンプルコード

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

public class SwingFrame {
    public static void main(String[] args) {
        // フレームタイトルを指定したフレームの生成
        JFrame frame = new JFrame("Swing");

        // 「×ボタン」によるアプリケーションの終了
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // レイアウトマネージャの指定
        frame.setLayout(new BorderLayout());

        // フレームサイズの指定
        // -> setBounds()メソッドで表示位置とまとめて指定可能
        frame.setSize(400, 200);

        // 表示位置の指定
        // -> setBounds()メソッドでフレームサイズとまとめて指定可能
        frame.setLocation(100, 100);

        // モニターサイズに合わせた表示位置の指定
        frame.setLocationRelativeTo(null);

        // フレームの表示
        frame.setVisible(true);
    }
}

実行結果

Frame.png


イベントハンドリング

イベント検知時にリスナによって呼び出されるイベントハンドラは、関数インタフェースであるActionListenerインタフェースの
actionPerformed()メソッドをオーバーライドして記述する。

ここで、イベントを検知する主なウィジェットは、以下の通り。

ウィジェット クラス 検知イベント
ボタン JButton ボタンのクリック
チェックボックス JCheckBox チェックボックスのクリック
ラジオボタン JRadioButton ラジオボタンのクリック
テキストフィールド JTextField テキストフィールドでのEnterの入力
パスワードフィールド JPasswordField パスワードフィールドでのEnterの入力

また、イベントの検知を待機する主なリスナインタフェースは、以下の通り。

ただし、複数のコールバックメソッドをもつリスナインタフェースの実装クラスではコールバックメソッドを全てオーバーライドする必要があるため、
MouseListenerKeyListenerWindowListenerは、特定のイベントのみを処理するイベントアダプタ(*Adapter)クラスが利用される。

インタフェース 検知イベント コールバックメソッド
ActionListener クリック・決定・実行 actionPerformed()
ChangeListener 状態の変化 stateChanged()
MouseListener マウス操作 クリック: mouseClicked()
カーソルイン: mouseEntered()
カーソルアウト: mouseExited()
ボタンのプレス: mousePressed()
ボタンのリリース: mouseReleased()
KeyListener キー操作 キーのプレス: keyPressed()
キーのリリース: keyReleased()
キーのタイプ: keyTyped()
WindowListener ウィンドウ操作 アクティブ時: windowActivated()
非アクティブ時: windowDeactivated()
クローズ前: windowClosing()
クローズ後: windowClosed()
最初の可視化時: windowOpened()
通常 → 最小化時: windowIconified()
最小化 → 通常時: windowDeiconified()

サンプルコード

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

public class SwingEvent {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Event Handler");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.setSize(400, 400);

        // ラベルの生成・ContentPaneへの追加
        JLabel label = new JLabel("Click following buttons.");
        frame.add(label, BorderLayout.NORTH);

        // ボタンの生成・イベントリスナ定義・ContentPaneへの追加
        // -> ActionListenerインタフェースの実装クラスを利用する場合
        JButton button1 = new JButton("button 1");
        button1.addActionListener(new bActionListener());
        frame.add(button1, BorderLayout.WEST);

        // ボタンの生成・イベントリスナ定義・ContentPaneへの追加
        // -> ActionListenerインタフェースを利用する場合
        JButton button2 = new JButton("button 2");
        button2.addActionListener(new ActionListener() {
            // イベントハンドラ
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Button 2 is clicked.");

            }
        });
        frame.add(button2, BorderLayout.CENTER);

        // ボタンの生成・イベントリスナ定義・ContentPaneへの追加
        // -> ラムダ式で記述する場合
        JButton button3 = new JButton("button 3");
        button3.addActionListener((ActionEvent e) -> {
            System.out.println("Button 3 is clicked.");
        });
        frame.add(button3, BorderLayout.EAST);

        frame.setVisible(true);
    }
}

// リスナクラス(ActionListenerインタフェースの実装クラス)
class bActionListener implements ActionListener {
    // イベントハンドラ
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Button 1 is clicked.");
    }
}

実行結果

イベントハンドラ.png


用語集

用語 内容
キャンバス(canvas) ウィンドウ全体を1つのグラフィック領域と捉える画面設計手法
ウィジェット(widget) ウィンドウを画面部品の集まりと捉える画面設計手法
ペイン(pane) フレームによって管理される、ウィジェットを保持する1つの枠組み
イベントドリブンモデル(event driven model) イベントハンドラを定義するプログラミングモデル
1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4