---
category: swing
folder: TabbedPaneWithButton
title: JTabbedPaneの余白にJButtonを配置
tags: [JTabbedPane, OverlayLayout, JButton, UIManager]
author: aterai
pubdate: 2008-03-03T14:07:59+09:00
description: JTabbedPaneのタブエリアに余白を作成し、そこにOverlayLayoutを使ってJButtonを配置します。
image: https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTUOdUT3wI/AAAAAAAAAls/N2JYE_Dcr_Y/s800/TabbedPaneWithButton.png
---
* Summary [#summary]
`JTabbedPane`のタブエリアに余白を作成し、そこに`OverlayLayout`を使って`JButton`を配置します。
#download(https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTUOdUT3wI/AAAAAAAAAls/N2JYE_Dcr_Y/s800/TabbedPaneWithButton.png)
* Source Code Examples [#sourcecode]
#code(link){{
ClippedTitleTabbedPane tabs = new ClippedTitleTabbedPane() {
@Override public void updateUI() {
String key = "TabbedPane.tabAreaInsets";
UIManager.put(key, null); // uninstall
super.updateUI();
// setAlignmentX(Component.LEFT_ALIGNMENT);
// setAlignmentY(Component.TOP_ALIGNMENT);
// System.out.println(button.getAlignmentY());
// button.setAlignmentY(Component.TOP_ALIGNMENT);
// System.out.println(button.getAlignmentY());
UIManager.put(key, getButtonPaddingTabAreaInsets());
super.updateUI(); // reinstall
}
@Override public float getAlignmentX() {
return LEFT_ALIGNMENT;
}
@Override public float getAlignmentY() {
return TOP_ALIGNMENT;
}
private Insets getButtonPaddingTabAreaInsets() {
Insets ti = getTabInsets();
Insets ai = getTabAreaInsets();
Dimension d = button.getPreferredSize();
FontMetrics fm = getFontMetrics(getFont());
int tih = d.height - fm.getHeight()
- ti.top - ti.bottom - ai.bottom;
return new Insets(
Math.max(ai.top, tih),
d.width + ai.left,
ai.bottom,
ai.right);
}
}
}}
* Description [#explanation]
* Description [#description]
上記のサンプルは、`JTabbedPane`でタブブラウザ風の動作を実現するために、以下のような設定を行っています。
- タブエリアの左上にあるボタンをクリックするとタブが追加する
- メニューからすべてのタブを削除する
- タブエリアに余裕がある場合は`80px`、無い場合は(タブエリアの幅/タブ数)と常にタブ幅は一定
-- 折り返しやスクロールが発生するとレイアウトが崩れることを防ぐための設定
- 以下の手順でコンポーネントの追加を実行
-- [[JTabbedPaneの余白にJCheckBoxを配置>Swing/TabbedPaneWithCheckBox]]
- ボタンの幅だけ`tabAreaInsets`の左余白を拡大する
-- `UIManager.getInsets("TabbedPane.tabAreaInsets")`などを使用するため`Synth`など(`GTK`, `Nimbus`)の`LookAndFeel`には対応していない
-- [https://bugs.openjdk.org/browse/JDK-6634504 Nimbus L&F: java.lang.NullPointer Exception throws when extended BaseUI Components]
- `OverlayLayout`で`JButton`と`JTabbedPane`(上で作った余白に)を重ねて表示
-- このため`JTabbedPane.TOP`にしか対応していない
----
- `JTabbedPane`の左端ではなく右端に`JButton`を配置するサンプル
#code{{
import java.awt.*;
import javax.swing.*;
public class TabbedPaneWithButtonTest {
public Component makeUI() {
JTabbedPane tabs = new JTabbedPane();
tabs.setAlignmentX(Component.RIGHT_ALIGNMENT);
tabs.setAlignmentY(Component.TOP_ALIGNMENT);
tabs.addTab("Tab 1", new JLabel("1"));
tabs.addTab("Tab 2", new JLabel("2"));
JButton button = new JButton("https://ateraimemo.com/");
button.setAlignmentX(Component.RIGHT_ALIGNMENT);
button.setAlignmentY(Component.TOP_ALIGNMENT);
JPanel p = new JPanel();
p.setLayout(new OverlayLayout(p));
p.add(button);
p.add(tabs);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
throw new IllegalArgumentException(ex);
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TabbedPaneWithButtonTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
}}
* Reference [#reference]
- [http://www.famfamfam.com/lab/icons/mini/ famfamfam.com: Mini Icons]
-- アイコンを借用
- [[OverlayLayoutの使用>Swing/OverlayLayout]]
- [[JTabbedPaneの余白にJCheckBoxを配置>Swing/TabbedPaneWithCheckBox]]
- [[JTabbedPaneのタイトルをクリップ>Swing/ClippedTabLabel]]
- [https://community.oracle.com/thread/1389350 Swing - Any layout suggestions for this?]
- [[JTabbedPaneのタブエリアレイアウトを変更して一覧表示ボタンなどを追加する>Swing/TabAreaLayout]]
* Comment [#comment]
#comment
#comment