JavaFXで各種サイズ制御


この記事について

将来的に書く予定の「JavaFX で DynamoDB Viewer作ってみた」記事の1ステップ。
結構大きな話になると思うので、少しずつ技術ポイント毎に記事を書いて、ある一定程度の要件を満たせた段階で前述まとめ記事書く予定。

第一回記事:DynamoDBの情報を読み込んでJavaFXで表示してみる
第二回記事:JavaFXで動的にテーブル列を設定する
第三回記事:AWS java SDKでDynamoDBテーブル情報を取得してみる
第四回記事:JavaFX の TableView の選択範囲をクリップボードにコピーする。
第五回記事:JavaFX でコンポーネント作って動的生成してみる
第六回記事:DynamoDBのデータ型をjava SDKから把握してみる。
第七回記事:JavaFXでジェネリック使って入力ダイアログ作成してみる

※これまでの記事が基本になってます。メソッドなど細かい部分で再説明していない部分があります。不明点などありましたらコメントなど頂けたら対応しようと思います。

今回の追加機能

  • テーブル読み込み時のタブが追加された時にそのタブを選択する様に
  • 要素の数、子要素の数が多い時にダイアログ表示不備修正
    • 表示する要素数が多い時にスクロールする様に
    • その時にヘッダは固定
    • 子要素が多い時(ラベルが長い時)対応
    • ウィンドウサイズ変更時に値列の幅が変動する様に
    • 編集エディタの幅がちゃんと画面サイズに連動して変わる様に

現在の進捗

この時点でのソース(github)

前回までの問題点

テストデータでない実際のデータで使ってみると、詳細ダイアログにて下記問題点がある事に気づく。これらを改善していく。

  • 要素数が多いとダイアログが画面高さよりも高くなってしまう。
  • 要素表示文字列が長いと(要素の子要素が多いと)ダイアログが画面幅よりも広くなってしまう。
  • 要素表示文字列が長いと、編集エディトの幅とずれる

改善方針

要素数が多い場合の問題(縦方向問題)

  • スクロール出来る様にする

要素表示文字列が長い場合の問題(横方向問題)

  • Labelが最大幅をはみ出たらEllipsis(... 表示)をする
  • 画面サイズに応じてデータ表示列の最大幅を変える

改善

修正前レイアウト階層

DialogPane
 ┗ GridPane
  ┗ HBox(データ要素列)
   ┗ TextField, Label等のデータ要素

縦方向問題

1.間にScrollPaneを挟む。

DialogPane
 ┗ ScrollPane
  ┗ GridPane
   ┗ HBox(データ要素列)
    ┗ TextField, Label等のデータ要素

これだけだと、初期表示時に要素分の高さを確保してしまう。

2.ScrollPane#setMaxHeight を指定

Rectangle2D で画面サイズを取得し、setMaxHeight を使用。ついでにsetMaxWidthも。

追加部分
        Rectangle2D screenSize2d = Screen.getPrimary().getVisualBounds();
        scrollPane.setMaxWidth(screenSize2d.getWidth());
        scrollPane.setMaxHeight(screenSize2d.getHeight());

こんな感じで、スクロール可能になった。これで縦方向の問題は解消した。

横方向問題

AnchorPaneを挟む

SceneBuilderではScrollPaneを追加すると、普通ではAnchorPaneが挟まる。それを適用する。

DialogPane
 ┗ ScrollPane
  ┗ AnchorPane(グリッドとの隙間0にする)
   ┗ GridPane
    ┗ HBox(データ要素列)
     ┗ TextField, Label等のデータ要素

これだけでは特に変化は起こらない。テスト用画面で見ると、AnchorPane(緑に着色)がScrollPane(赤に着色)についてきていない。ScrollPaneの特性を考えると間違えていない。やりたいのは横方向はScrollせずに縦だけScrollする事。さらに、GridPaneを画面リサイズに応じて変更。さらにその中の指定列だけ可変幅にする事。もしかしたら設定だけで出来るかもしれないが、ここはもうプログラムチックにする方法を取る。

サイズ変更リスナー追加

それに必要な以下の修正も加える。

  • ColumnConstraints を使ってGridPaneの列幅設定
  • 横スクロールバーは見せない様に
  • 幅変更リスナーを追加(計算して第2列の幅設定)
テスト修正
        ColumnConstraints colContraint0 = new ColumnConstraints();
        ColumnConstraints colContraint1 = new ColumnConstraints();
        ColumnConstraints colContraint2 = new ColumnConstraints();
        colContraint0.setPrefWidth(100);
        colContraint1.setPrefWidth(300);
        colContraint2.setPrefWidth(100);
        grid.getColumnConstraints().add(colContraint0);
        grid.getColumnConstraints().add(colContraint1);
        grid.getColumnConstraints().add(colContraint2);

        scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
        ChangeListener<Number> stageSizeListener = (observable, oldValue, newValue) -> {
            grid.getColumnConstraints().get(1).setPrefWidth(newValue.doubleValue() - 200.0);
        };
        scrollPane.widthProperty().addListener(stageSizeListener);

大分イメージに近づいた。これを実際のソースに適用する。

TextFieldの自動幅調整

現在、値列はHBoxで入っている。TextFieldはHBoxに入っている状態でなければ自動的に幅調整がされた。それをそのまま使用する。

LabelのEllipsis表示

label.setWrapText(false);
label.setTextOverrun(OverrunStyle.ELLIPSIS);

するだけでOKだった。

次回予定

次こそはデータや要素の追加、データ型チェックなど。

参考にさせて頂いたページ

皆さんの良記事

JavaFXで使う各種Pane
gridpane resize