概要

JInternalFrameのタイトル文字列幅を取得し、その値をアイコン化した場合のJDesktopIconの幅として適用します。

サンプルコード

JDesktopPane desktop = new JDesktopPane();
desktop.setDesktopManager(new DefaultDesktopManager() {
  @Override public void iconifyFrame(JInternalFrame f) {
    Rectangle r = this.getBoundsForIconOf(f);
    r.width = f.getDesktopIcon().getPreferredSize().width;
    f.getDesktopIcon().setBounds(r);
    super.iconifyFrame(f);
  }
});
desktop.add(createFrame("looooooooooooong title #", 1));
desktop.add(createFrame("#", 0));
// ...
JInternalFrame f = new JInternalFrame(t + i, true, true, true, true);
f.setDesktopIcon(new JInternalFrame.JDesktopIcon(f) {
  @Override public Dimension getPreferredSize() {
    Dimension d = super.getPreferredSize();
    String title = f.getTitle();
    Font font = getFont();
    if (Objects.nonNull(font)) {
      FontMetrics fm = getFontMetrics(font);
      int titleW = SwingUtilities.computeStringWidth(fm, title);

      // @see javax/swing/plaf/basic/BasicInternalFrameTitlePane.java
      // Handler#minimumLayoutSize(Container)
      // Calculate width.
      int buttonsW = 22;
      if (f.isClosable()) {
        buttonsW += 19;
      }
      if (f.isMaximizable()) {
        buttonsW += 19;
      }
      if (f.isIconifiable()) {
        buttonsW += 19;
      }
      Insets i = getInsets();
      // 2: Magic number of gap between icons
      d.width = buttonsW + i.left + i.right + titleW + 2 + 2 + 2;
      // 27: Magic number for NimbusLookAndFeel
      d.height = Math.min(27, d.height);
      System.out.println("BasicInternalFrameTitlePane: " + d.width);
    }
    return d;
  }

  // private void testWidth() {
  //   Dimension dim = getLayout().minimumLayoutSize(this);
  //   System.out.println("minimumLayoutSize: " + dim.width);
  //
  //   int buttonsW = SwingUtils.stream(this)
  //       .filter(AbstractButton.class::isInstance)
  //       .mapToInt(c -> c.getPreferredSize().width)
  //       .sum();
  //   System.out.println("Total width of all buttons: " + buttonsW);
  // }
});
View in GitHub: Java, Kotlin

解説

  • JInternalFrame.JDesktopIcon#getPreferredSize()メソッドをオーバーライドしJInternalFrameをアイコン化した場合の推奨サイズを変更
    • JInternalFrameをアイコン化した場合のサイズを変更する
    • JInternalFrameのタイトル文字列を取得しSwingUtilities.computeStringWidth(...)で文字列幅を計算する
      • デフォルトのJInternalFrameではSwingUtilities2.stringWidth(...)メソッドなどで省略された場合などを考慮しているがこのサンプルでは無視する
    • ClosableButtonMaximizableButtonIconifiableButtonなどの合計幅を計算する
      • javax/swing/plaf/basic/BasicInternalFrameTitlePane.javaHandler#minimumLayoutSize(Container)メソッドを参照して値を取得(22 + 19 + 19 + 19)
      • JButtonを計算してgetPreferredSize().widthを合計しても値が異なる?
    • 内余白を加算して推奨サイズを返す
      • super.getPreferredSize()の値が初回とそれ以降で変化するため、このサンプルでは高さに固定値を使用
  • DefaultDesktopManager#iconifyFrame(JInternalFrame)メソッドをオーバーライドしてJInternalFrameをアイコン化した場合の実サイズを変更
  • このサンプルはNimbusLookAndFeelのみ対応でWindowsLookAndFeelなどには未対応

参考リンク

コメント