概要

Component上に重ねて配置した検索用ダイアログの位置をアニメーション付きで変更するレイアウトマネージャーを作成し、その表示非表示をキー入力で切り替えます。

サンプルコード

JPanel p = new JPanel() {
  @Override public boolean isOptimizedDrawingEnabled() {
    return false;
  }
};
p.setLayout(new BorderLayout(0, 0) {
  @Override public void layoutContainer(Container parent) {
    synchronized (parent.getTreeLock()) {
      Insets insets = parent.getInsets();
      int width = parent.getWidth();
      int height = parent.getHeight();
      int top = insets.top;
      int bottom = height - insets.bottom;
      int left = insets.left;
      int right = width - insets.right;
      Component nc = getLayoutComponent(parent, BorderLayout.NORTH);
      if (Objects.nonNull(nc)) {
        Dimension d = nc.getPreferredSize();
        int vsw = UIManager.getInt("ScrollBar.width");
        nc.setBounds(right - d.width - vsw, yy - d.height, d.width, d.height);
      }
      Component cc = getLayoutComponent(parent, BorderLayout.CENTER);
      if (Objects.nonNull(cc)) {
        cc.setBounds(left, top, right - left, bottom - top);
      }
    }
  }
});
p.add(searchBox, BorderLayout.NORTH);
p.add(new JScrollPane(tree));
View in GitHub: Java, Kotlin

解説

  • BorderLayout#layoutContainer(...)メソッドをオーバーライドし、BorderLayout.NORTHで追加した検索ダイアログをOverlayLayoutのようにBorderLayout.CENTERで追加したJTreeに重ねて配置
    • BorderLayout.CENTERBorderLayout.NORTHのみ対応
    • 検索ダイアログの幅はBorderLayoutBorderLayout.NORTH配置のように親コンポーネントの幅まで拡張せず、FlowLayoutなどと同様にPreferredSize固定
    • UIManager.getInt("ScrollBar.width")で取得したスクロールバーの幅だけ右側に余白を作成して検索ダイアログを配置
  • Timerを使った検索ダイアログ位置変更によるスライドインアニメーション
  • JTreeを配置したJScrollPaneと検索用ダイアログ(JPanel)といった子コンポーネント同士がオーバーラップするので、親のJPanelisOptimizedDrawingEnabled()falseを返すようにオーバーライドする必要がある
  • 検索用ダイアログが開くと内部のJTextFieldにフォーカスが移動するようにAncestorListenerを設定
  • JTreeのノード検索
    • 参考: JTreeのノードを検索する
    • Ctrl+F: 検索用ダイアログの表示非表示切り替え
    • Esc: 検索用ダイアログを閉じる
    • Enter: JTreeのノードを検索

参考リンク

コメント