概要

JFrameを最大化した後でJSplitPaneDividerの位置を変更する場合のテストをします。

サンプルコード

class SplitPaneWrapper extends JPanel {
  private int prevState = Frame.NORMAL;
  private final JSplitPane splitPane;

  protected SplitPaneWrapper(JSplitPane splitPane) {
    super(new BorderLayout());
    this.splitPane = splitPane;
    add(splitPane);
    EventQueue.invokeLater(() -> splitPane.setDividerLocation(.5));
  }

  private static int getOrientedSize(JSplitPane sp) {
    return (sp.getOrientation() == JSplitPane.VERTICAL_SPLIT)
           ? sp.getHeight() - sp.getDividerSize()
           : sp.getWidth()  - sp.getDividerSize();
  }

  @Override public void doLayout() {
    int size = getOrientedSize(splitPane);
    final double proportionalLocation = splitPane.getDividerLocation() / (double) size;
    super.doLayout();
    int state = ((Frame) SwingUtilities.getWindowAncestor(splitPane)).getExtendedState();
    if (splitPane.isShowing() && state != prevState) {
      EventQueue.invokeLater(() -> {
        int s = getOrientedSize(splitPane);
        int iv = (int) Math.round(s * proportionalLocation);
        System.out.format("DividerLocation: %d%n", iv);
        splitPane.setDividerLocation(iv);
      });
      prevState = state;
    }
  }
}
View in GitHub: Java, Kotlin

解説

  • MAXIMIZED_BOTH: keep the same splitting ratioが未選択の場合:
    • JSplitPane#setResizeWeight(0d)に設定されているので、JFrameをマウスでリサイズしても上コンポーネントの高さが維持される
  • MAXIMIZED_BOTH: keep the same splitting ratioが選択されている場合:
    • JSplitPaneをラップするJPaneldoLayout()メソッドをオーバーライドして最大化、通常化の前後で上下コンポーネントの高さの比率を維持する
    • EventQueue.invokeLater(...)を使って後でJSplitPane#setDividerLocation(int)でディバイダの位置を調節
    • デフォルト(MAXIMIZED_BOTH: keep the same splitting ratioチェックボックスのチェックを外している状態):
      • 例えば、最大化後にディバイダをすこし上に移動してJFrameを元に戻す(縮小)と上コンポーネントの方が下コンポーネントより高くなる
    • JSplitPane#setDividerLocation(double)は内部でJSplitPane#setDividerLocation(int)を呼び出しているがその変換の際に値を切り捨てているので、このサンプルでは最大化、元に戻す(縮小)を行なっても同じ値になるように四捨五入するよう変更している

参考リンク

コメント