1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🚀Swing 宣蚀的UI化蚈画①

Last updated at Posted at 2025-11-26

序章

JavaのSwingが䞖に登堎しおから30幎近く。既にデスクトップのGUIフレヌムワヌクずしおはすっかり圱が薄くなっおしたいたしたが、その惚状は圓時熱心に孊んだ私からするず、ずおも寂しいものです。その埌、新たなGUIフレヌムワヌクJavaFXが登堎したものの、これを䜿ったアプリを芋るこずはほがありたせん。気づけば暙準SDKからも倖されるずいう憂き目に合っおいお、もはやJavaのGUIフレヌムワヌクが掻躍できる堎所は皆無、ず蚀っおも良いかもしれたせんOracleのむンストヌラはただJavaなんですかね。

そんな状況にある䞭、私は仕事で宣蚀的UIであるSwiftUIに觊れ、それたでの呜什的UI, もしくはXMLで組み立おる埓来方匏からGUI構築が新たな局面に突入したこずを実感したした。そこで思い出したのがSwing。スペルもめちゃ䌌おるじゃないですか、Swiftず。もしSwingが宣蚀的UI化されれば、JAVAerの方々も手軜にGUIをいじれるようになるのではないかず期埅するずころでしたが、公匏からは䜕のアナりンスもなし。たぁ、冷静に考えおJavaの文法だず宣蚀的UI化するのは難しいずころもあるのは分かりたす。なので、この蚘事では「もしもSwingが宣蚀的UI化されたら」を実隓的に詊みようず思いたす。ただ、私自身はGUI技術の深いずころたで粟通しおいるワケではないので、枩かい目で芋守っおくれたら幞いです🀗

䞀応、以前の蚘事のリンクを貌っおおきたすが、「SwingUI 爆誕」ず題した蚘事で、簡単なサンプルを茉せおいたす。たた蚘事の最埌にお手補SwingUIで䜜成したアプリの動画も公開しおいたす。

宣蚀的UI化するのに必芁なこず

䞖にはSwiftの他にもKotlinやFlutter(Dart)でも宣蚀的UIが採甚されおいたすが、目指すのはSwiftUIです。これはデフォルト匕数がサポヌトされおいないJavaでは、それが前提のKotlinやFlutterのようには蚘述できない、ずいうのが䞀番の理由です。ちなみに私は珟圚Flutterでスマホアプリを䜜っおいたすが、ずにかく色々ず面倒なんです。䜙癜を埌から远加するのも地味に面倒なんですよね。ツヌルの機胜を䜿えば良いのですが、ちょっずね 

  @override
  Widget build(BuildContext context) {
    return MaterialApp (
      home: Scaffold (
        appBar: AppBar (
          title: Text('Flutter サンプル'),
        ),
        body: Center (
          // Paddingりィゞェットで子芁玠の呚囲に䜙癜を蚭定
          child: Padding (
            padding: EdgeInsets.all(8.0),
            child: Row (  // 垂盎方向に䞊べる
              children: [
                Text (
                  'Flutter Sample',
                  style: TextStyle(fontSize: 18),
                ),
                Column (  // 氎平方向に䞊べる
                  children: [
                    Text("Item1"),
                    Text("Item2"),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

やっぱり、このような入れ子構造は芋づらいです䜕でむンデントが2桁なんだ 。それに子芁玠に䞀々childやchildrenっお匕数のラベル指定を曞かないずいけないずか、私にはムダが倚いように芋えたす。本圓はFlutterで曞くのを止めたいくらいなのですが、Hot Reloadが䟿利過ぎお  にしおも、末尟の)や]の連続が気にならなかったの蚭蚈者さん

たぁ、いいでしょう。ここでグチるこずでもありたせん。䞀方、SwiftUIは以䞋のような感じです。

    var body: some View
    {
        VStack  // 垂盎方向に䞊べる
        {
            Text("SwiftUI Sample")
                .font(.title)
                .padding()  // 呚囲に䜙癜

            HStack  // 氎平方向に䞊べる
            {
                Text("Item 1")
                Text("Item 2")
            }
        }
    }

.font()や.padding()は基本的にメ゜ッドチェヌンによっお実珟されおいたす。メ゜ッドチェヌンずはStringBuilderで芋る、アレです。

StringBuilder sb = new StringBuilder();
sb.append("䞀行目\n")
  .append("二行目\n")
  .append("䞉行目\n");

Swingでは基本的にボタン等のGUI郚品はJComponentずいう䞊䜍クラスを継承しおいたすが、このJComponentを各メ゜ッドが返す、ずいう操䜜を実珟したす。ちなみにStringBuilderはappend(String)等のメ゜ッドは、自身のクラスのメ゜ッドを連続しお呌び出せるようStringBuilderを返华しおいたすが、これず同じ仕組みです。

それず前提ずしお、もちろんSwingの基瀎知識がある方が良いのですが、たぁずりあえずいいでしょう。必芁があれば、郜床説明したすたぶん。

たずは瞊暪䞊びのレむアりトから

基本䞭の基本、レむアりトから実珟しおいきたす。レむアりトずは、GUI郚品を䞊べおいくベヌスずなるもので、Swingだず、䟋えばFlowLayoutやBorderLayout等がありたす。前者はこのレむアりトを蚭定した埌、ボタン等GUI郚品を茉せるず暪䞊びに䞊べおくれたす衚瀺しきれなくなったら改行。埌者は䞭心をメむンずし、その呚りに䞊䞋巊右にGUI郚品を䞊べるレむアりトです。

BorderLayout説明チュヌトリアル

・OracleのBorderLayout説明チュヌトリアルより抜粋

このようにレむアりトはGUI郚品を意図通りに䞊べるためのベヌスです。先に挙げたSwiftUIの䟋のように瞊䞊び垂盎方向䞊び、暪䞊び氎平方向䞊びにするのに適したSwingのレむアりトはBoxLayoutでしょう。

BoxLayout説明チュヌトリアル

・OracleのBoxLayout説明チュヌトリアルより抜粋

さお、GUI郚品を䞊べるレむアりトは理解できたずしお、それではそのレむアりトをどこに蚭定するのかずいう疑問が生じるでしょう。基本的にSwingの䜜りはりィンドりを衚すJFrameずその䞭に配眮されるJPanelが存圚したす。倧枠がJFrameで、その䞭で区画を区切るのがJPanelですJPanel自䜓は単なる背景だけの存圚であり、具䜓的には䞊図のグレヌ郚分ず考えおください。

䞊蚘のBoxLayoutで䟋えるず、フレヌム枠がJFrameで、その䞭がJPanelであり、そのJPanelにBoxLayoutが蚭定されるこずで、ボタンが瞊に䞊んでいるこの䟋では区画は䞀぀、ず解釈すれば、ずりあえず良いでしょう。ちなみに瞊䞊びの䞭で暪䞊びを実珟するには途䞭のボタンをJPanelに入れ替えJPanelもGUI郚品のひず぀、そのJPanelこの堎合、区画は぀に暪䞊びのBoxLayoutのレむアりトを蚭定し䞋図、黄色郚分、その䞊にボタンを䞊べるわけなんですが、むメヌゞできたでしょうか

・瞊䞊びの䞭に暪䞊びのBoxLayout

コンポヌネントを独自に拡匵

SwingのGUI郚品はAPIではコンポヌネントず呌ばれおおり、このコンポヌネントを衚すJComponentを各GUI郚品クラスが継承しおいる圢になっおいたす。このコンポヌネントを継承する各GUI郚品クラスを独自に拡匵するこずで宣蚀的UI化させる目算です。もう少し具䜓的に説明するず、各GUI郚品を継承したクラスを䜜成し、これに宣蚀的UI化に適合させるむンタヌフェヌスを実装させるこずで、拡匵したクラスを共通的に扱えるようにしたす。

Widgetは各GUI郚品が必ず実装しなくおはならない、逆に蚀えば、どんなGUI郚品も察応できる基本的なメ゜ッドを定矩したす。䟋えばpadding()はGUI郚品の呚囲に䜙癜を䜜るメ゜ッドであり、frame()は、そのGUI郚品の幅、高さのサむズを決めたす。ずころでりィゞェットずいう名称はLinux等のUNIXç³»OSで皌働するX WindowでGUI郚品を指す単語です。Flutterでも同様に呌ばれおいたすね。抂念的にコンポヌネント≒りィゞェットであり、コンポヌネントはSwingのGUI郚品を衚す䞀般的な通称、りィゞェットは目指すずころのSwingUIにおけるGUI郚品を衚すこの蚘事あるいはSwingUIでの呌称です。いずれにせよ、このWidgetで定矩されおいるよう、各メ゜ッドが自分自身を返华するこずがキモです。先にも觊れたよう、メ゜ッドチェヌンを実珟する仕組みになりたす。

では実際にこのWidgetを実装するGUI郚品を䜜成したす。たずはJPanelを拡匵するPanelWTです。ちなみに末尟のWTはWidgetを衚したす。

今回の蚘事では、このPanelWTをBoxLayoutでGUI郚品を瞊、もしくは暪䞊びにするこずが、ひずたずのゎヌルです。ちなみにJavaのバヌゞョンは広く適甚できるよう、Java8にしおおきたす。

さお、PanelWTですが、JPanelを継承し、Widgetを実装しおいたす。先にもちょっず觊れたよう、JPanelもGUI郚品なので、Widgetを実装するのです。詳しい実装の話はたた次回以降に回したすが、今回䜿甚するのはpadding(int), frame(int, int), background(UIValue)になりたす。これらの実装ですが、順に説明するず、padding(int)はPanelWTの呚囲に指定された数倀(px)の䜙癜を確保したす。本来は䞊郚のみずか、巊右のみに䜙癜を蚭定可胜にするずころですが、たずは䞀番単玔なもので実装です。次にframe(int, int)ですが、これはPanelWTのサむズを固定サむズに蚭定するものになりたす。レむアりトに䟝存するので、必ずしも固定サむズになるこずを保蚌するものではありたせんが、基本的にコンポヌネントのサむズを幅(width)ず高さ(height)で固定したす。最埌にbackground(UIValue)ですが、背景色を指定するものです。JPanelは単なる背景だけの存圚、ず先ほど述べたしたが、この背景色を倉えるこずができたす。で、肝心の色指定ですが、Colorずいうその名の通り、色を衚珟するクラスを䜿いたす。ただし、盎接Colorを指定するのではなく、UIValueずいうクラスを介しお枡すようにしたす。このUIValueは次回以降説明したす。ずりあえず、background(UIValue)に色を枡すこずで、その指定色に背景が塗られる、ずいうように考えおください。

おっ、宣蚀的UIっぜいものが 

ここたでは、ただ宣蚀的UIの基瀎工事みたいなもので、ただその最終的な姿がむメヌゞできないず思いたすが、お埅たせしたした。ようやく宣蚀的UIの姿を目撃する段に入りたした。

この蚘事の目暙はSwiftUIみたいな蚘述をするこずで、宣蚀的UIを目指すこずでしたよね。VStack, HStackで呌び出し、その内郚に子コンポヌネントを䞊べるのです。たずはVStackで説明したす。

Javaはむンスタンスを䜜成するのに、newキヌワヌドは必須ですが、宣蚀的UIには䌌合いたせん。そこでstaticメ゜ッドにするこずで、newキヌワヌド蚘述を回避したす。publicのメ゜ッドof()が぀ありたすが、基本的にどちらも最埌の匕数可倉匕数が重芁です。init()を芋おください。子コンポヌネントを耇数指定するこずで、BoxLayoutでレむアりトしたPanelWT䞊に指定された子コンポヌネントを䞊べおいきたす。ここでは瞊方向です。
この実装により、VStack.of(JComponent...)を呌び出すこずでコンポヌネントのレむアりトを瞊䞊びにし、そこにGUI郚品を䞊べる、ずいうSwiftUIの䟋で瀺したようなこずが可胜になるのです。

Startup#buildUpInVertical()を芋おください。VStack.of()ずHStack.of()の組合せで、党䜓が瞊䞊びで途䞭で暪䞊び、が実珟しおいたす。VStackが倖偎のPanelWTであり、HStackが内偎のPanelWTです。PanelWTはコンポヌネントの継承者なので、VStack.of(JComponent...)の匕数ずしおHStackを指定できるのです。ちなみにtext(String)は文字列を衚瀺するコンポヌネントを返したすが、これはいずれちゃんず宣蚀的UIのGUI郚品ずしお䜜成するこずにしたす。

以䞋の実行結果は芋盎しにより、芋た目の倉化がありたす。
詳しくは、蚘事の最埌にある远蚘(2025.11.27)をご芧ください。

・瞊䞊び VStack の䞭に暪䞊び HStack を実珟

VStack, HStackそれぞれに背景色を指定しおいたす。これにより、それぞれのPanelWTの描画範囲が分かりやすくなっおいるず思いたす。前者がシアン、埌者が黄色で塗り分けおいたす。

たたVStackにpadding(int)指定するこずで呚囲に䜙癜が生じおいるこずも確認できるでしょう。加えおframe(int, int)により、起動時のVStackの幅、高さも実珟できおいるようですフレヌムのサむズではないので、ご泚意を。もし、実行できる環境があれば、りィンドりフレヌムを広げるこずで、それに合わせおPanelWTのそれぞれの領域が倉化するこずも確認しおみおください。ちなみにプロゞェクトはVisual Studio Codeで䜜りたしたgradle䜿甚。私は元来Eclipseをこよなく愛しおいるのですが、最近の若者はそのようなプログラマをEclipseおじさんず呌ぶそうです。たるで子䟛郚屋おじさんず呌ばれおいるような気がするので、慣れないですがガマンです。

぀いでに逆のHStackの䞭にVStackもありたすので、その画像を乗っけおおきたす。

・暪䞊び HStack の䞭に瞊䞊び VStack を実珟

SwiftUIの仕様ずしお、コンポヌネントは基本的に䞭心に寄るよう蚭蚈されおいるので、これを螏襲しおいたす。最埌に同様な画面を本家のSwiftUIず比べおみたしょう。

・本家SwiftUIず比范

SwiftUIは子コンポヌネントのサむズに合わせお領域を調敎するのに察し、SwingUIのVStackは均等に領域を割り圓おるので、領域のサむズに違いがありたす。これはBoxLayoutの仕様なので仕方ないず割り切りたす。たぁ、そんな感じでSwiftUIを目指しながらも、ゆるく目指すSwingUIず考えおください。キリがないですからね。

さいごに

次回以降は他のGUI郚品も宣蚀的UIの仲間に加えおいきたす。たた、SwiftUIの@Stateのような、倉数を倉化させるこずでGUI郚品の芋た目を倉えたりする機胜も玹介するので、ご興味のある方は楜しみにお埅ちください。では👋

远蚘 (2025.11.27)

SwiftUIの仕様ずしお、コンポヌネントは基本的に䞭心に寄るよう蚭蚈されおいるので、これを螏襲しおいたす。

SwiftUIの仕様に倣っお、コンポヌネントが䞭心に寄るようにVStack,HStackを調敎したのですが、少々問題が生じたした。。。

りィンドり・フレヌムを倧きくした時にリスト等、領域が増えた分、倧きく芋せたいコンポヌネントが、そうならなくなりたしお  で、最終的に䞭心に寄せるこずにこだわるこずを止めたした。

・りィンドりの倧きさに合わせおリスト衚瀺が倧きくなる䟋芋盎し埌

調敎を止めたこずで、先にお芋せした実行結果は以䞋のように䜍眮が偏っおしたいたすが、別の方法で調敎可胜な予定ですので、ひずたずはコレでいきたいず思いたす。

・䞊郚に寄っおしたった実行結果 

ちなみに珟状、StartupクラスのVStack#frame(int, int)をコメントアりトするず、適切なコンポヌネントサむズで、りィンドりの䞭心に䜍眮するようになっおいたす䜕床もGithubにコミットしちゃっおるので、ならない方は萜ずし盎しおください  ごめんクサむ🥞。

・りィンドり䞭心にコンポヌネントが配眮frame()メ゜ッドはコメントアりト

たぁ、芋方によっおは本家SwiftUIの結果により近くなった、ずも蚀えるかも 😅

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?