Swing/TabAreaPopupMenu のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/TabAreaPopupMenu へ行く。
- 1 (2024-01-29 (月) 05:49:01)
- 2 (2024-02-24 (土) 11:01:29)
- 3 (2024-02-25 (日) 12:27:31)
- 4 (2024-02-28 (水) 21:30:15)
- 5 (2024-06-10 (月) 14:20:19)
- category: swing folder: TabAreaPopupMenu title: JTabbedPaneのTabAreaで開くJPopupMenuを設定する tags: [JTabbedPane, JPopupMenu] author: aterai pubdate: 2024-01-29T05:46:34+09:00 description: JTabbedPaneのタブ上とTabArea内では異なるJPopupMenuを開くよう設定します。 image: https://drive.google.com/uc?id=1gYHccpOFLZywYrdW0agN_qhRAitbFgtF
概要
JTabbedPane
のタブ上とTabArea
内では異なるJPopupMenu
を開くよう設定します。
Screenshot
Advertisement
サンプルコード
JTabbedPane tabbedPane = new JTabbedPane() {
private final JPopupMenu popup1 = makeTabPopupMenu();
private final JPopupMenu popup2 = makeTabAreaPopupMenu();
@Override public void updateUI() {
super.updateUI();
EventQueue.invokeLater(() -> {
SwingUtilities.updateComponentTreeUI(popup1);
SwingUtilities.updateComponentTreeUI(popup2);
setComponentPopupMenu(popup1);
});
}
@Override public Point getPopupLocation(MouseEvent e) {
int idx = indexAtLocation(e.getX(), e.getY());
if (idx < 0 && getTabAreaBounds().contains(e.getPoint())) {
setComponentPopupMenu(popup2);
} else {
setComponentPopupMenu(popup1);
}
return super.getPopupLocation(e);
}
private Rectangle getTabAreaBounds() {
Rectangle tabbedRect = getBounds();
Rectangle compRect = Optional.ofNullable(getSelectedComponent())
.map(Component::getBounds)
.orElseGet(Rectangle::new);
int tabPlacement = getTabPlacement();
if (isTopBottomTabPlacement(tabPlacement)) {
tabbedRect.height = tabbedRect.height - compRect.height;
if (tabPlacement == BOTTOM) {
tabbedRect.y += compRect.y + compRect.height;
}
} else {
tabbedRect.width = tabbedRect.width - compRect.width;
if (tabPlacement == RIGHT) {
tabbedRect.x += compRect.x + compRect.width;
}
}
return tabbedRect;
}
private boolean isTopBottomTabPlacement(int tabPlacement) {
return tabPlacement == TOP || tabPlacement == BOTTOM;
}
};
View in GitHub: Java, Kotlin解説
- タブ上用
popup1
とTabArea
内用popup2
に2
種類のJPopupMenu
を用意 JTabbedPane#getPopupLocation(MouseEvent)
をオーバーライドしてクリック位置によって使用するJPopupMenu
を切り替えるJTabbedPane#getPopupLocation(MouseEvent)
はJTabbedPane#getComponentPopupMenu()
がnull
で未設定の場合は実行されないので、初期状態で適当なJPopupMenu
を設定しておく必要があるTabArea
内、かつJTabbedPane#indexAtLocation(...)
が負でクリック位置がタブ上でない場合はTabArea
内用のpopup2
をJTabbedPane#setComponentPopupMenu(popup2)
で設定- それ以外の場合はタブ上用の
popup1
をJTabbedPane#setComponentPopupMenu(popup1)
で設定- タブコンテナ内のコンポーネントにマウスリスナーが未設定の場合タブ上用の
popup1
がJPopupMenu
として使用される
- タブコンテナ内のコンポーネントにマウスリスナーが未設定の場合タブ上用の
- ひとつの
JPopupMenu
でJPopupMenu#show(invoker, x, y)
をオーバーライドし、このxy
座標で使用するJMenuItem
を入れ替える方法もある- どちらを使用する場合も動作中に
LookAndFeel
を変更する場合は手動でSwingUtilities.updateComponentTreeUI(...)
を実行して現在使用していないJPopupMenu
やJMenuItem
のLookAndFeel
を更新する必要がある
- どちらを使用する場合も動作中に
JTabbedPane#setTabComponentAt(...)
で設定したタブコンポーネントにJPopupMenu
を設定して以下のようにJTabbedPane#getComponentPopupMenu()
で切り替える方法もあるが、マウスクリックによるタブ移動が不可になる場合がある
@Override public JPopupMenu getComponentPopupMenu() {
int idx = getSelectedIndex();
Component c = getTabComponentAt(idx);
JPopupMenu popup;
if (idx>= 0 && c instanceof JComponent) {
popup = ((JComponent) c).getComponentPopupMenu();
} else {
popup = super.getComponentPopupMenu();
}
return popup;
}
参考リンク
- JTabbedPaneのタブをドラッグ&ドロップ
TabArea
領域の取得方法は上記のリンク先のサンプルとおなじものを使用