
SwingはJava用のGUIウィジェットツールキットです。[ 1 ]これはOracleのJava Foundation Classes(JFC)の一部であり、 Javaプログラムにグラフィカルユーザーインターフェイス(GUI)を提供するAPIです。
Swing は、以前のAbstract Window Toolkit (AWT)よりも洗練された GUIコンポーネントセットを提供するために開発されました。Swing は、複数のプラットフォームのルック アンド フィールを模倣したルック アンド フィールを提供するとともに、基盤となるプラットフォームとは無関係なルック アンド フィールをアプリケーションに与えるプラグイン可能なルック アンド フィールもサポートしています。AWT よりも強力で柔軟なコンポーネントを備えています。ボタン、チェックボックス、ラベルなどの馴染みのあるコンポーネントに加えて、Swing はタブ付きパネル、スクロール ペイン、ツリー、テーブル、リストなどの高度なコンポーネントも提供しています。[ 2 ]
AWTコンポーネントとは異なり、Swingコンポーネントはプラットフォーム固有のコードで実装されていません。代わりに、SwingコンポーネントはすべてJavaで記述されているため、プラットフォームに依存しません。
2008年12月、Sun Microsystems(Oracleの前身)は、Swingの後継となることを意図したCSS / FXMLベースのフレームワークであるJavaFXをリリースした。[ 3 ]
Internet Foundation Classes (IFC) は、 Netscape Communications Corporationが開発した Java 用のグラフィックス ライブラリで、1996 年 12 月 16 日に初めてリリースされました。1997 年 4 月 2 日、Sun MicrosystemsとNetscape Communications Corporation は、 IFC を他のテクノロジーと統合してJava Foundation Classes を形成する意向を発表しました。[ 4 ]「Java Foundation Classes」は後に「Swing」と改名されました。
Swing は、アプリケーション コードを大幅に変更することなく、アプリケーション内のすべてのコンポーネントの外観を変更できるメカニズムを導入しました。プラグイン可能な外観のサポートが導入されたことで、Swing コンポーネントはプラットフォーム非依存性の利点を維持しながら、ネイティブ コンポーネントの外観をエミュレートできるようになりました。当初は別個のダウンロード可能なライブラリとして配布されていた Swing は、リリース 1.2 以降、 Java Standard Editionの一部として含まれています。[ 5 ] Swing クラスとコンポーネントはjavax.swingパッケージ階層に含まれています。
Swing の後継であるJavaFXの開発は2005 年に始まり、2 年後の JavaOne 2007 で正式に発表されました。[ 6 ] JavaFX は 2011 年にオープンソース化され、2012 年に Oracle JDK のダウンロードに含まれるようになりました。JavaFX は、軽量であること、CSSスタイリングがあること、洗練されたデザイン コントロールがあること、 FXMLと Scene Builderを使用していることなど、いくつかの利点により Swing に取って代わっています。[ 3 ] 2018 年に、JavaFX は OpenJFX プロジェクトの下で OpenJDK の一部となり、開発のペースが加速されました。[ 7 ]
Swingを担当したJavaクライアントチームのメンバーには、James Gosling(アーキテクト)、Rick Levenson(マネージャー)、Amy FowlerとHans Muller(共同テクニカルリード)、Tom Ball、Jeff Dinkins、Georges Saab、[ 8 ] Tim Prinzing、Jonni Kanerva、Jeannette HungとJim Graham(2Dグラフィックス)が含まれていました。[ 9 ]
Swingは、 Java用のプラットフォーム非依存の「モデル・ビュー・コントローラ」GUIフレームワークであり、シングルスレッドのプログラミングモデルに従います。[ 10 ]さらに、このフレームワークは、SwingベースのGUIのコード構造とグラフィック表示の間に抽象化レイヤーを提供します。
Swingは完全にJavaで記述されているため、プラットフォームに依存しません。すべてのSwingクラスの完全なドキュメントは、Java APIガイド(バージョン6)またはJavaプラットフォーム標準版8 API仕様(バージョン8)に記載されています。
Swing は高度にモジュール化されたアーキテクチャであり、指定されたフレームワーク インターフェイスのさまざまなカスタム実装を「プラグイン」することができます。ユーザーは、Java の継承メカニズムを介して、これらのコンポーネントの独自のカスタム実装を提供して、デフォルトの実装をオーバーライドできますLookAndFeel。
Swingはコンポーネントベースのフレームワークであり、そのコンポーネントはすべて最終的にJComponentクラスから派生しています。Swingオブジェクトは非同期的にイベントを発火し、バインドされたプロパティを持ち、コンポーネント固有のドキュメント化されたメソッドセットに応答します。SwingコンポーネントはJavaBeansコンポーネントであり、JavaBeans仕様に準拠しています。
Swingはランタイムメカニズムと間接的な構成パターンに大きく依存しているため、設定の根本的な変更に実行時に対応できます。例えば、Swingベースのアプリケーションは、実行時にユーザーインターフェースをホットスワップできます。さらに、ユーザーは独自のルックアンドフィール実装を提供できるため、アプリケーションコードにプログラム的な変更を加えることなく、既存のSwingアプリケーションのルックアンドフィールを統一的に変更できます。
Swingの高い柔軟性は、ネイティブのホストオペレーティングシステム(OS)のGUIコントロールをオーバーライドして自身を表示できるという、その固有の機能に反映されています。Swingは、ネイティブのユーザーインターフェースツールキットを呼び出すのではなく、Java 2D APIを使用してコントロールを「描画」します。そのため、Swingコンポーネントには対応するネイティブOSのGUIコンポーネントがなく、基盤となるグラフィックスGUIで可能なあらゆる方法で自身をレンダリングできます。
しかし、Swing コンポーネントは、その根幹において、AWTコンテナに依存しています。これは、Swing がJComponentAWT の Container を拡張しているためです。これにより、Swing はホスト OS の GUI 管理フレームワークに接続でき、重要なデバイス/画面マッピングや、キーの押下やマウスの移動などのユーザー操作も処理できます。Swing は、基盤となる (OS 固有の) コンポーネントに対して、独自の (OS に依存しない) セマンティクスを単に「転置」するだけです。たとえば、すべての Swing コンポーネントは、(AWT) Container で定義されている component.paint() の呼び出しに応じて、グラフィック デバイスにレンダリング結果を描画します。ただし、描画を OS ネイティブの「ヘビーウェイト」ウィジェットに委任する AWT コンポーネントとは異なり、Swing コンポーネントは独自のレンダリングを担当します。
この転置と分離は視覚的なものにとどまらず、Swing がコンポーネント包含階層内で発生するイベントに対して独自の OS 非依存のセマンティクスを管理および適用する点にも及びます。一般的に、Swing アーキテクチャは、さまざまな OS GUI セマンティクスをシンプルかつ汎用的なパターンにマッピングするタスクを AWT コンテナに委任します。そして、その汎用的なプラットフォーム上に、JComponentモデルという形で独自の豊富で複雑な GUI セマンティクスを確立します。
Swing ライブラリは、モデル ビュー コントローラソフトウェアデザイン パターン[ 11 ]を多用しており、これは、表示されるデータと、それを表示するユーザー インターフェイス コントロールを概念的に分離します。このため、ほとんどの Swing コンポーネントには関連付けられたモデル(Javaインターフェイスで指定されます) があり、プログラマはさまざまなデフォルト実装を使用したり、独自の実装を提供したりできます。フレームワークは、すべての具体的なコンポーネントに対してモデル インターフェイスのデフォルト実装を提供します。Swing フレームワークの一般的な使用では、カスタム モデルの作成は必要ありません。フレームワークは、デフォルトで透過的にJComponentSwing ライブラリ内の対応する子クラスに関連付けられている一連のデフォルト実装を提供します。一般に、テーブル、ツリー、場合によってはリストなどの複雑なコンポーネントのみが、アプリケーション固有のデータ構造に関するカスタム モデル実装を必要とする場合があります。Swing アーキテクチャが実現する可能性をよく理解するために、テーブルとリストのカスタム モデルがDAOおよび/またはEJBサービスのラッパーであるという仮想的な状況を考えてみましょう。
通常、Swing コンポーネント モデル オブジェクトは、関連付けられた JComponent が使用する (概念) データ モデルに対して発生するイベントとアクセス可能なプロパティを定義する簡潔なインターフェイスを提供する役割を担います。全体的な MVC パターンは疎結合の協調オブジェクト関係パターンであるため、モデルはイベント リスナーをデータ モデル オブジェクトにアタッチするためのプログラム的な手段を提供します。これらのイベントはモデル中心 (例: テーブル モデルでの「行挿入」イベント) であり、JComponent特殊化によってGUI コンポーネントにとって意味のあるイベントにマッピングされます。
例えば、 には、テーブルが表形式データにアクセスする方法を記述するインターフェースを記述する というJTableモデルがありますTableModel。このデフォルトの実装は、2 次元配列に対して動作します。
Swing JComponent のビュー コンポーネントは、概念的な GUI コントロールをグラフィカルに表現するために使用されるオブジェクトです。GUI フレームワークとしての Swing の特徴は、ネイティブ ホスト OS の GUI コントロールを使用するのではなく、プログラムによってレンダリングされた GUI コントロールに依存している点です。Java 6 Update 10より前は、ネイティブ コントロールを使用する AWT コントロールと Swing コントロールを GUI で混在させる場合、この違いが問題の原因となっていました ( AWT コンポーネントと Swing コンポーネントの混在を参照)。
最後に、視覚的な構成と管理に関して言えば、Swingは絶対レイアウト(コンポーネントの正確な位置とサイズを指定する)よりも相対レイアウト(コンポーネント間の位置関係を指定する)を優先します。このような「流動的な」視覚的順序付けへの偏りは、オリジナルのJava GUIツールキットの設計と開発の基盤となったアプレットオペレーティング環境に由来しています。(概念的には、このレイアウト管理の考え方は、ブラウザにおけるHTMLコンテンツのレンダリングの考え方と非常によく似ており、前者と同じ一連の懸念事項に対処しています。)

Javaの初期バージョンから、 Abstract Window Toolkit (AWT)の一部は、ユーザーインターフェイスコンポーネント向けにプラットフォーム非依存のAPIを提供してきました。AWTでは、各コンポーネントは、基盤となるウィンドウシステムに固有のネイティブなピアコンポーネントによってレンダリングおよび制御されます。
対照的に、Swing コンポーネントは、オペレーティングシステムのウィンドウツールキットでネイティブ リソースの割り当てを必要としないため、軽量であるとよく言われます。AWT コンポーネントは、重量級コンポーネントと呼ばれます。[ 12 ]
Swing API の大部分は、AWT を直接置き換えるというよりは、AWT を補完する拡張機能です。実際、Swing のすべてのトップレベル コンポーネント ( JApplet、JDialog、JFrame、 および) は AWT トップレベル コンテナを継承しているため、すべての Swing 軽量インターフェースは最終的に AWT 重量コンポーネント内に存在します。Java 6 Update 10JWindowより前は、 Z オーダーの互換性の問題から、同じウィンドウ内で軽量コンポーネントと重量コンポーネントの両方を使用することは一般的に推奨されていませんでした。しかし、それ以降の Java バージョンではこれらの問題が修正され、Swing コンポーネントと AWT コンポーネントの両方を Z オーダーの問題なく 1 つの GUI で使用できるようになりました。
Swingが軽量コンポーネントを描画するために使用するコアレンダリング機能は、JFCの一部であるJava 2Dによって提供されます。
Standard Widget Toolkit (SWT) は、 IBMが開発し、現在はEclipseコミュニティが保守している競合ツールキットです。SWT の実装は、AWT の主要コンポーネントと共通点が多く、基盤となるネイティブウィンドウツールキットとのより正確な互換性といった利点がある一方で、プログラミングモデルにおいてネイティブプラットフォームへの依存度が高まるという欠点があります。
SWTとSwingのパフォーマンスについては、かなりの議論と憶測がありました。SWTはJNIに大きく依存しているため、GUIコンポーネントとJavaがデータを通信する必要がある場合は遅くなりますが、データモデルがGUIにロードされるとレンダリングが速くなるという意見もありましたが、どちらの方向も確認されていません。[ 13 ] 2005年に行われたかなり徹底的なベンチマークでは、一般的なケースではSwingもSWTも明らかに他方を上回っていないという結論が出ました。[ 14 ]
このSwingアプリケーションの例は、「Hello, world!」というメッセージが表示された単一のウィンドウを作成します。
// Hello.java (Java SE 8) import javax.swing.* ;public class Hello extends JFrame { public Hello () { super ( "Hello World" ); setDefaultCloseOperation ( WindowConstants . EXIT_ON_CLOSE ); add ( new JLabel ( "Hello, world!" )); pack (); setVisible ( true ); }public static void main ( String [] args ) { SwingUtilities . invokeLater ( Hello :: new ); } }最初のパッケージimportには、そのパッケージに含まれるすべての公開クラスとインターフェースが含まれていますjavax.swing。
クラスHelloは、タイトルバーと閉じるコントロールextendsを備えたウィンドウを実装します。JFrameJFrame
コンストラクタHello()は"Hello World"、まずスーパークラスのコンストラクタを呼び出し、ウィンドウのタイトルとして使用されるパラメータを渡すことでフレームを初期化します。次に、setDefaultCloseOperation(int)から継承したメソッドを呼び出しJFrame、タイトル バーの閉じるコントロールが選択されたときのデフォルトの動作をに設定します。これにより、フレームが閉じられたときにが破棄され(単に非表示になるのではなく)、Java 仮想マシンが終了してプログラムが終了できるようになります。次に、文字列「Hello, world!」用のが作成され、スーパークラスから継承したメソッドが呼び出されてラベルがフレームに追加されます。スーパークラスから継承したメソッドが呼び出されて、ウィンドウのサイズが調整され、その内容がレイアウトされます。スーパークラスから継承したメソッドがブール値パラメータとともに呼び出され、フレームが表示されます。WindowConstants.EXIT_ON_CLOSE JFrameJLabeladd(Component)Containerpack()WindowsetVisible(boolean)Componenttrue
このmain()メソッドは、プログラムの開始時にJava仮想マシンによって呼び出されます。新しいフレームをインスタンス化しますHello。コードは、このメソッドを使用してAWTイベントディスパッチスレッドinvokeLater(Runnable)からコンストラクタを呼び出し、コードがスレッドセーフに実行されるようにします。フレームが表示された後、すべてのSwingトップレベルウィンドウが破棄されるまでイベントディスパッチスレッドがアクティブなままであるため、メソッドを終了してもプログラムは終了しません。main

以下は、比較的シンプルなSwingベースのプログラムです。JFrameラベルとボタンを含むウィンドウ(a)を表示します。
import java.awt.FlowLayout ; import javax.swing.JButton ; import javax.swing.JFrame ; import javax.swing.JLabel ; import javax.swing.WindowConstants ; import javax.swing.SwingUtilities ; public class SwingExample implements Runnable { @Override public void run () { // ウィンドウを作成しますJFrame f = new JFrame ( "Hello World!" ); // ウィンドウが閉じられたときの動作を設定しますf . setDefaultCloseOperation ( WindowConstants . EXIT_ON_CLOSE ); // ボタンがラベルの上に配置されないようにレイアウトマネージャを追加しますf . setLayout ( new FlowLayout ()); // ラベルとボタンを追加しますf . add ( new JLabel ( "Hello, world!" )); f . add ( new JButton ( "Press me!" )); // ウィンドウ内のコンポーネントを配置しますf . pack (); // デフォルトでは、ウィンドウは表示されません。表示させます。f.setVisible ( true ); } public static void main ( String [] args ) { // イベントキューで適切なタイミングでアプリケーションが実行されるようにスケジュールします。SwingUtilities.invokeLater ( new SwingExample ( ) ); }}Swing コンポーネントのインスタンス化と処理はすべて Runnable インターフェイスを実装することによって行われることに注目してください。これは、メイン メソッドで作成されたメソッド ) を使用してイベント ディスパッチ スレッドで実行されます ( Swing とスレッド セーフティを参照)。この手法を使用せずに Swing コードを実行することもできます (たとえば、Runnable を実装せず、すべてのコマンドを run メソッドから main メソッドに移動することによって)が、Swing はスレッド セーフではないため、複数のスレッドからリソースを呼び出すとスレッド干渉やメモリ一貫性エラーが発生する可能性があるため、この手法を使用するのが良いとされています。[ 15 ]SwingUtilities.invokeLater(Runnable)
テキストフィールドを使用すると、ユーザーはアプリケーションにテキストやデータを入力できます。Swingでテキストフィールドを作成するのは簡単です。JTextFieldオブジェクトをインスタンス化して、コンテナに追加するだけです。
import javax.swing.* ;public class TextFieldExample { public static void main ( String [] args ) { SwingUtilities . invokeLater (() -> { // JFrame を作成しますJFrame frame = new JFrame ( "Text Field Example" );// JTextFieldを作成しますJTextField textField = new JTextField ( 20 );// テキストフィールドをJFrameフレームに追加します。frame.add ( textField );// JFrameのサイズを設定し、表示させるframe.setSize ( 300 , 200 ) ; frame.setVisible ( true ) ; } ) ; } }テキストフィールドの機能を強化することで、ユーザーとのインタラクションが向上します。DocumentListenerインターフェースをアタッチすることで、テキストコンテンツの変更を動的に監視し、入力データのリアルタイム検証、書式設定、または自動補完を実現できます。
テキストフィールドの入力を検証することは、データの整合性を確保し、エラーを防止するために非常に重要です。Swing は、正規表現、入力マスク、カスタム検証ロジックなど、複数の検証手法を提供しています。InputVerifier インターフェイスを実装することで、特定の検証ルールを定義し、入力が無効な場合にユーザーに即座にフィードバックを提供できます。[ 16 ]
この例では、javax.swing.JFrame をスーパークラスとし、そこに独自のウィジェット (この場合は JButton) を追加します。
import javax.swing.JFrame ; import javax.swing.JButton ; import javax.swing.JOptionPane ; import javax.swing.SwingUtilities ;import java.awt.event.ActionListener ; import java.awt.event.ActionEvent ;public class Sample extends JFrame { public Sample () { super (); this . setTitle ( "HelloApp" ); this . getContentPane (). setLayout ( null ); this . setBounds ( 100 , 100 , 180 , 140 ); this . add ( makeButton ()); this . setVisible ( true ); this . setDefaultCloseOperation ( EXIT_ON_CLOSE ); }private JButton makeButton () { final JButton b = new JButton (); b.setText ( "Click me!" ) ; b.setBounds ( 40 , 40 , 100 , 30 ) ; b.addActionListener ( ( ActionEvent e ) - > JOptionPane.showMessageDialog ( b , " Hello World ! " )); return b ; }public static void main ( String [] args ) throws InvocationTargetException , InterruptedException { // Swing の呼び出しはイベントディスパッチスレッドによって実行される必要があります。SwingUtilities . invokeAndWait (() -> new Sample ()); } }JFrame はデフォルトのレイアウトマネージャとして java.awt.BorderLayout を使用するため、このメソッドを使用してレイアウトを null に設定しますContainer.setLayout(LayoutManager)。BorderLayout では、コンテナに追加されたものはすべて中央に配置され、他のウィジェットを収容するために引き伸ばされます。実際の GUI アプリケーションのほとんどは、すべてを絶対座標に配置するのではなく、レイアウトマネージャを使用することを好みます。[ 17 ]
Foundation ClassesはJava 2プラットフォームの中核となり、以下が含まれます。Project SwingのGUIコンポーネントセット、ドラッグ&ドロップ、新しい2DおよびAWTグラフィックス機能と印刷サポートを提供するJava 2D API、Javaルックアンドフィールインターフェース、新しいアクセシビリティAPI
It is hard to give a rule-of-thumb where SWT would outperform Swing, or vice versa. In some environments (e.g., Windows), SWT is a winner. In others (Linux, VMware hosting Windows), Swing and its redraw optimization outperform SWT significantly. Differences in performance are significant: factors of 2 and more are common, in either direction.