• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JTabbedPaneの余白にJButtonを配置
#navi(../)
#tags(JTabbedPane, OverlayLayout, JButton, UIManager)
RIGHT:Posted by &author(aterai); at 2008-03-03
* JTabbedPaneの余白にJButtonを配置 [#g997f976]
``JTabbedPane``のタブエリアに余白を作成し、そこに``OverlayLayout``を使って``JButton``を配置します。
---
title: JTabbedPaneの余白にJButtonを配置
tags: [JTabbedPane, OverlayLayout, JButton, UIManager]
author: aterai
pubdate: 2008-03-03T14:07:59+09:00
description: JTabbedPaneのタブエリアに余白を作成し、そこにOverlayLayoutを使ってJButtonを配置します。
---
* 概要 [#g997f976]
`JTabbedPane`のタブエリアに余白を作成し、そこに`OverlayLayout`を使って`JButton`を配置します。

- &jnlp;
- &jar;
- &zip;
#download(https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTUOdUT3wI/AAAAAAAAAls/N2JYE_Dcr_Y/s800/TabbedPaneWithButton.png)

#ref(https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTUOdUT3wI/AAAAAAAAAls/N2JYE_Dcr_Y/s800/TabbedPaneWithButton.png)

** サンプルコード [#l9d78f5a]
* サンプルコード [#l9d78f5a]
#code(link){{
final JButton b = new ToolBarButton(icon);
b.addActionListener(new ActionListener() {
  @Override public void actionPerformed(ActionEvent e) {
    tabs.addTab("qwerqwer", new JLabel("yetyet"));
  }
});
tabs = new ClippedTitleTabbedPane() {
  @Override public void updateUI() {
    UIManager.put("TabbedPane.tabAreaInsets", null); //uninstall
    super.updateUI();
    setAlignmentX(0.0f);
    setAlignmentY(0.0f);
    b.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
    b.setAlignmentX(0.0f);
    b.setAlignmentY(0.0f);
    tabAreaInsets = getTabAreaInsets();
    UIManager.put("TabbedPane.tabAreaInsets",
                  getButtonPaddingTabAreaInsets(b, getTabInsets(), tabAreaInsets));
    super.updateUI();
  }
  private Insets tabAreaInsets = null;
};
JPanel p = new JPanel();
p.setLayout(new OverlayLayout(p));
button.setAlignmentX(0.0f);
button.setAlignmentY(0.0f);
tabPane.setAlignmentX(0.0f);
tabPane.setAlignmentY(0.0f);
p.add(button);
p.add(tabPane);
p.add(tabs);
}}

#code{{
public InsetsUIResource getButtonPaddingTabAreaInsets(JButton b) {
  int bw = b.getPreferredSize().width;
  int bh = b.getPreferredSize().height;
  Insets insets = UIManager.getInsets("TabbedPane.tabInsets");
  Insets ti = (insets!=null)?insets:new Insets(0,0,0,0);
  insets = UIManager.getInsets("TabbedPane.tabAreaInsets");
  Insets ai = (insets!=null)?insets:new Insets(0,0,0,0);
  FontMetrics metrics = getFontMetrics(getFont());
  int tih = bh - metrics.getHeight()-ti.top-ti.bottom-ai.bottom;
  return new InsetsUIResource(Math.max(ai.top, tih), bw+ai.left, ai.bottom, ai.right);
//Insets ti = UIManager.getInsets("TabbedPane.tabInsets");
//Insets ai = UIManager.getInsets("TabbedPane.tabAreaInsets");
public Insets getButtonPaddingTabAreaInsets(JButton b, Insets ti, Insets ai) {
  FontMetrics fm = b.getFontMetrics(b.getFont());
  int tih = b.getPreferredSize().height-fm.getHeight()-ti.top-ti.bottom-ai.bottom;
  return new Insets(Math.max(ai.top, tih), b.getPreferredSize().width+ai.left, ai.bottom, ai.right);
}
}}

** 解説 [#f485c989]
* 解説 [#f485c989]
上記のサンプルは、タブブラウザ風の動作となるように設定しています。

- タブエリアの左上にあるボタンをクリックするとタブが追加される
- メニューからすべてのタブを削除する
- タブエリアに余裕がある場合は``80px``、無い場合は(タブエリアの幅/タブ数)と、常にタブ幅は一定
- タブエリアに余裕がある場合は`80px`、無い場合は(タブエリアの幅/タブ数)と、常にタブ幅は一定
-- 折り返しや、スクロールが発生するとレイアウトが崩れるため

コンポーネントの追加には、以下の方法を使用しています(比較:[[JTabbedPaneの余白にJCheckBoxを配置>Swing/TabbedPaneWithCheckBox]])。

- ボタンの幅だけ、``tabAreaInsets``の左余白を拡大する
-- ``UIManager.getInsets("TabbedPane.tabAreaInsets")``などを使用するため、``Synth``など(``GTK``, ``Nimbus``)の``LookAndFeel``には対応していない
- ボタンの幅だけ、`tabAreaInsets`の左余白を拡大する
-- `UIManager.getInsets("TabbedPane.tabAreaInsets")`などを使用するため、`Synth`など(`GTK`, `Nimbus`)の`LookAndFeel`には対応していない
-- [http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6634504 Nimbus L&F: java.lang.NullPointer Exception throws when extended BaseUI Components]
- ``OverlayLayout``で、``JButton``と``JTabbedPane``(上で作った余白に)を重ねて表示
-- このため、``JTabbedPane.TOP``にしか対応していない
- `OverlayLayout`で、`JButton`と`JTabbedPane`(上で作った余白に)を重ねて表示
-- このため、`JTabbedPane.TOP`にしか対応していない

** 参考リンク [#j34dcca9]
* 参考リンク [#j34dcca9]
- [http://www.famfamfam.com/lab/icons/mini/ famfamfam.com: Mini Icons]
-- 追加アイコンを拝借しています。
- [[OverlayLayoutの使用>Swing/OverlayLayout]]
- [[JTabbedPaneの余白にJCheckBoxを配置>Swing/TabbedPaneWithCheckBox]]
- [[JTabbedPaneのタイトルをクリップ>Swing/ClippedTabLabel]]
- [https://forums.oracle.com/thread/1389350 Swing - Any layout suggestions for this?]

** コメント [#b7c186f2]
* コメント [#b7c186f2]
#comment
#comment