JTabbedPaneの選択タブ切り替えをマウスクリック後に変更する
Total: 7
, Today: 7
, Yesterday: 0
Posted by aterai at
Last-modified:
Summary
JTabbedPane
の選択タブ切り替えをマウスプレスの直後ではなく、クリック完了後に変更します。
Screenshot

Advertisement
Source Code Examples
class TabClickLayerUI extends LayerUI<JTabbedPane> {
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override protected void processMouseEvent(MouseEvent e, JLayer<? extends JTabbedPane> l) {
JTabbedPane tabs = l.getView();
if (Objects.equals(tabs, e.getComponent())) {
if (e.getID() == MouseEvent.MOUSE_CLICKED) {
updateSelectedTab(tabs, e);
} else if (e.getID() == MouseEvent.MOUSE_PRESSED) {
e.consume();
}
}
}
private static void updateSelectedTab(JTabbedPane tabs, MouseEvent e) {
int index = SwingUtilities.isLeftMouseButton(e)
? tabs.indexAtLocation(e.getX(), e.getY())
: -1;
if (index >= 0 && tabs.isEnabledAt(index)) {
tabs.setSelectedIndex(index);
if (tabs.isRequestFocusEnabled()) {
tabs.requestFocus(FocusEvent.Cause.MOUSE_EVENT);
}
}
}
}
View in GitHub: Java, KotlinDescription
- 上: デフォルト
JTabbedPane
のデフォルトはMetalLookAndFeel#createMouseListener(...)
などで生成されたMouseListener
がmousePressed
イベントを受信したとき、JTabbedPane#setSelectedIndex(index)
を実行して選択タブが変更される- このため、単純に
JTabbedPane
にMouseListener
を追加してもMetalLookAndFeel#createMouseListener(...)
で生成したMouseListener
が先に実行されて動作を変更できない
- 中:
JTabbedPane#setTabComponentAt(...)
でタブコンポーネントをJButton
に変更- タブコンポーネントとして
JButton
を設定し、そのJButton
にActionListener
を追加してマウスクリック後にJTabbedPane#setSelectedIndex(index)
を実行する - タブコンポーネントの
JButton
にMouseMotionListener
を追加し、マウス移動イベントをJTabbedPane#dispatchEvent(...)
で転送することでロールオーバー状態を更新している - タブコンポーネントの
JButton
にJButton#setInheritsPopupMenu(true)
を設定してもJTabbedPane
本体に設定したJPopupMenu
を呼び出せない?
- タブコンポーネントとして
- 下:
JLayer
でラップしてLayerUI#processMouseEvent(...)
をオーバーライドJTabbedPane
をJLayer
でラップしてマウスイベントを上書きすることで選択タブ切り替えの挙動を変更するJTabbedPane
全体をJLayer
でラップするため、子のタブコンテンツ(このサンプルではJScrollPane
やJTextArea
)へのマウスイベントも上書きしてしまわないよう、JLayer#getView()
で取得可能なラップされたJTabbedPane
とMouseEvent#getComponent()
で取得可能なイベント発生元のコンポーネントが同一の場合のみマウスイベントを上書きしているMouseEvent.MOUSE_PRESSED
の場合はMouseEvent#consume()
を実行して消費してMetalLookAndFeel#createMouseListener(...)
で生成したMouseListener
のmousePressed
を処理されないようにするMouseEvent.MOUSE_CLICKED
の場合はJTabbedPane#setSelectedIndex(index)
を実行して選択タブを切り替える
- マウスプレス後にマウスカーソル位置を変更するとクリックイベントが発生しないので、これを変更する場合は
MouseEvent.MOUSE_RELEASED
が対象タブ領域内で発生したら選択タブを切り替えるよう修正する必要がある