Swing/TabbedPaneWithButton のバックアップの現在との差分(No.5)
TITLE:JTabbedPaneの余白にJButtonを配置
Posted by terai at 2008-03-03
JTabbedPaneの余白にJButtonを配置
JTabbedPaneのタブエリアに余白を作成し、そこにOverlayLayoutを使ってJButtonを配置します。- 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:
概要
JTabbedPane
のタブエリアに余白を作成し、そこにOverlayLayout
を使ってJButton
を配置します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
#screenshot
サンプルコード
#spanend
#spanadd
ClippedTitleTabbedPane tabs = new ClippedTitleTabbedPane() {
#spanend
@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
}
#spandel
**サンプルコード [#l9d78f5a]
#spanend
#spandel
#code{{
#spanend
#spandel
JPanel p = new JPanel();
#spanend
#spandel
p.setLayout(new OverlayLayout(p));
#spanend
#spandel
button.setAlignmentX(0.0f);
#spanend
#spandel
button.setAlignmentY(0.0f);
#spanend
#spandel
tabPane.setAlignmentX(0.0f);
#spanend
#spandel
tabPane.setAlignmentY(0.0f);
#spanend
#spandel
p.add(button);
#spanend
#spandel
p.add(tabPane);
#spanend
@Override public float getAlignmentX() {
return LEFT_ALIGNMENT;
}
#spanadd
#spanend
@Override public float getAlignmentY() {
return TOP_ALIGNMENT;
}
#spanadd
#spanend
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);
}
#spanadd
}
#spanend
View in GitHub: Java, Kotlin解説
上記のサンプルは、JTabbedPane
でタブブラウザ風の動作を実現するために、以下のような設定を行っています。
- タブエリアの左上にあるボタンをクリックするとタブが追加する
- メニューからすべてのタブを削除する
- タブエリアに余裕がある場合は
80px
、無い場合は(タブエリアの幅/タブ数)と常にタブ幅は一定- 折り返しやスクロールが発生するとレイアウトが崩れることを防ぐための設定
- 以下の手順でコンポーネントの追加を実行
- ボタンの幅だけ
tabAreaInsets
の左余白を拡大する-
UIManager.getInsets("TabbedPane.tabAreaInsets")
などを使用するためSynth
など(GTK
,Nimbus
)のLookAndFeel
には対応していない - Nimbus L&F: java.lang.NullPointer Exception throws when extended BaseUI Components
-
-
OverlayLayout
でJButton
とJTabbedPane
(上で作った余白に)を重ねて表示- このため
JTabbedPane.TOP
にしか対応していない
- このため
- -
-
JTabbedPane
の左端ではなく右端にJButton
を配置するサンプル
#spandel
public InsetsUIResource getButtonPaddingTabAreaInsets(JButton b) {
#spanend
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);
#spanadd
import java.awt.*;
#spanend
#spanadd
import javax.swing.*;
#spanend
#spanadd
#spanend
#spanadd
public class TabbedPaneWithButtonTest {
#spanend
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"));
#spanadd
#spanend
JButton button = new JButton("https://ateraimemo.com/");
button.setAlignmentX(Component.RIGHT_ALIGNMENT);
button.setAlignmentY(Component.TOP_ALIGNMENT);
#spanadd
#spanend
JPanel p = new JPanel();
p.setLayout(new OverlayLayout(p));
p.add(button);
p.add(tabs);
return p;
}
#spanadd
#spanend
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);
});
}
}
解説
上記のサンプルは、以下のような動作*1の仕様になっています。- タブエリアの左上にあるボタンをクリックするとタブが追加される
- メニューからすべてのタブを削除する
- タブエリアに余裕がある場合は80pt、無い場合は(タブエリアの幅/タブ数)と、常にタブ幅は一定
- 折り返しや、スクロールが発生するとレイアウトが崩れるため
参考リンク
- famfamfam.com: Mini Icons
- アイコンを借用
- OverlayLayoutの使用
- JTabbedPaneの余白にJCheckBoxを配置
- JTabbedPaneのタイトルをクリップ
- Swing - Any layout suggestions for this?
- JTabbedPaneのタブエリアレイアウトを変更して一覧表示ボタンなどを追加する
- ボタンの幅だけ、tabAreaInsets の左余白を拡大する
- UIManager.getInsets("TabbedPane.tabAreaInsets")などを使用するため、Synthなど(GTK, Nimbus)のL&Fには対応していない
- Nimbus L&F: java.lang.NullPointer Exception throws when extended BaseUI Components
- OverlayLayout で、JButtonとJTabbedPane(上で作った余白に)を重ねて表示
- このため、JTabbedPane.TOP にしか対応していない
参考リンク
- famfamfam.com: Mini Icons
- 追加アイコンを拝借しています。
- OverlayLayoutの使用
- JTabbedPaneの余白にJCheckBoxを配置
- JTabbedPaneのタイトルをクリップ
- Swing - Any layout suggestions for this?