Java Swingのアーキテクチャとは?特徴とMVCモデルをわかりやすく解説
Java Swingは、Javaプログラム向けにグラフィカルユーザーインターフェース(GUI)を提供するAPI群です。Java Swingは、それ以前のAPIであるAbstract Window Toolkit(AWT)をベースに開発されました。AWTと比べて、より豊富で洗練されたGUIコンポーネントを備えており、シンプルな部品から複雑なツリーやテーブルまで幅広く利用できます。さらに、プラグイン可能なルック&フィール(Pluggable Look and Feel)機能により、Javaプログラムの外観を基盤となるプラットフォームから独立して制御できる点も大きな特長です。
Java Swingの主な特徴
Java Swingはプラットフォームに依存しない設計であり、MVC(Model-View-Controller)フレームワークに基づいて構築されています。ここからは、代表的な3つの特徴を詳しく見ていきましょう。
1. プラグイン可能なルック&フィール
Java Swingは複数のルック&フィールをサポートしており、現在ではWindows、UNIX、Motif、そしてJavaネイティブのMetalルック&フィールに対応しています。アプリケーションを再起動することなく実行時に外観を切り替えられるため、ユーザーは自分にとって最適な見た目をその場で自由に選択できます。
2. 軽量コンポーネント
一部のトップレベルコンテナを除き、すべてのSwingコンポーネントは軽量(Lightweight)です。これは、ホストOSに依存せず、Graphicsオブジェクトの描画プリミティブを使ってコンポーネント自身を描画することを意味します。その結果、AWTなどの従来のJava GUIアプリケーションと比較して、より高速な描画処理と少ないメモリ消費を実現しています。
3. 簡略化されたMVCアーキテクチャ
Java Swingは、各コンポーネントの背後にある設計思想として、簡略化されたModel-View-Controller(MVC)アーキテクチャを採用しています。これは「モデル・デリゲート(model-delegate)」と呼ばれる仕組みです。この設計では、各SwingコンポーネントがモデルとUIデリゲートを持ち、UIデリゲートがMVCにおけるビューとコントローラの役割を兼ねます。具体的には、UIデリゲートが画面の描画とGUIイベントの処理を担当し、モデルがコンポーネントの情報や状態の管理を担います。
サンプルコード
以下は、Model・View・Controllerの3つのクラスに分けてMVCアーキテクチャを実装したシンプルなSwingアプリケーションの例です。ボタンをクリックするたびにカウント値が増え、ラベルに表示されます。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
// モデル部分
class Model {
private int x;
public Model() {
x = 0;
}
public Model(int x) {
this.x = x;
}
public void setX(){
x++;
}
public int getX() {
return x;
}
}
// ビュー部分
class View {
private JFrame frame;
private JLabel label;
private JButton button;
public View(String text) {
frame = new JFrame("View");
frame.getContentPane().setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,200);
frame.setVisible(true);
label = new JLabel(text);
frame.getContentPane().add(label, BorderLayout.CENTER);
button = new JButton("Button");
frame.getContentPane().add(button, BorderLayout.SOUTH);
}
public JButton getButton() {
return button;
}
public void setText(String text) {
label.setText(text);
}
}
// コントローラ部分
class Controller {
private Model model;
private View view;
private ActionListener actionListener;
public Controller(Model model, View view) {
this.model = model;
this.view = view;
}
public void contol() {
actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
linkBtnAndLabel();
}
};
view.getButton().addActionListener(actionListener);
}
private void linkBtnAndLabel() {
model.setX();
view.setText(Integer.toString(model.getX()));
}
}
// メインクラス
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
// ルック&フィールの設定(システム標準を使用)
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) { }
Model model = new Model(0);
View view = new View("-");
Controller controller = new Controller(model,view);
controller.contol();
}
});
}
}
実行結果
プログラムを実行すると、中央にラベル、下部にボタンが配置されたウィンドウが表示されます。ボタンをクリックするたびにモデルのカウント値が1ずつ増加し、その値がラベルに反映される様子を確認できます。このように、状態管理(モデル)、表示(ビュー)、イベント処理(コントローラ)を分離することで、保守性と拡張性の高いGUIアプリケーションを構築できます。

-
【Java入門】長方形の周囲(外周)を求めるプログラムの作り方
長方形の周囲とは? この記事では、Javaを使って長方形の周囲(外周)を求める方法を解説します。長方形の周囲とは、長方形の4つの辺すべての長さを足し合わせた合計のことで、次の図のように「縦の辺2本」と「横の辺2本」の長さを合計したものに相当します。 長方形は向かい合う辺の長さが等しいという性質を持つため、周囲は次の式で計算できます。 周囲 = 2 ×(縦の長さ + 横の長さ) 入力と出力の例 たとえば、入力が次の値であるとします。 長方形の各辺の長さ:5, 8, 5, 8 このとき、期待される出力は次のとおりです。 Perimeter : 26 アルゴリズム 処理の流れは以下のようになりま
-
Java Swingはスレッドセーフではない?その理由とEDTの正しい使い方を解説
結論から言うと、Java Swingのコンポーネントはスレッドセーフではありません。複数のスレッドから同時にSwingコンポーネントへアクセスすると、描画の不整合やデッドロックなど予期しない動作を引き起こす可能性があります。Swingがスレッドセーフではない理由最大の理由は、コンポーネントの拡張(サブクラス化)を簡単にするためです。すべてのメソッドで同期処理を行うと、開発者がオーバーライドして独自のコンポーネントを作る際に、ロックの扱いまで意識する必要が生じ、設計が複雑になってしまいます。もう一つの理由は、ロックの取得・解放や状態の復元にかかるオーバーヘッドです。全メソッドをスレッドセーフにす