JPopupMenuに垂直JSliderを配置してJToggleButtonの上部に表示する
Total: 1632, Today: 1, Yesterday: 2
Posted by aterai at
Last-modified:
Summary
JPopupMenuに垂直JSliderを配置し、JToggleButtonに設定したJToolTipを表示するときにその上部に重ねて表示します。
Screenshot

Advertisement
Source Code Examples
JPopupMenu popup = new JPopupMenu();
popup.setLayout(new BorderLayout());
popup.addMouseWheelListener(InputEvent::consume);
UIManager.put("Slider.paintValue", Boolean.TRUE);
UIManager.put("Slider.focus", UIManager.get("Slider.background"));
JSlider slider = new JSlider(SwingConstants.VERTICAL, 0, 100, 80);
slider.addMouseWheelListener(e -> {
JSlider s = (JSlider) e.getComponent();
if (s.isEnabled()) {
BoundedRangeModel m = s.getModel();
m.setValue(m.getValue() - e.getWheelRotation() * 2);
}
e.consume();
});
popup.add(slider);
JToggleButton button = new JToggleButton("🔊") {
@Override public JToolTip createToolTip() {
JToolTip tip = super.createToolTip();
tip.addHierarchyListener(e -> {
long flg = e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED;
if (flg != 0 && e.getComponent().isShowing()) {
Dimension d = popup.getPreferredSize();
popup.show(this, (getWidth() - d.width) / 2, -d.height);
}
});
return tip;
}
@Override public Point getToolTipLocation(MouseEvent e) {
return new Point(getWidth() / 2, -getHeight());
}
@Override public void setEnabled(boolean b) {
super.setEnabled(b);
setText(b ? "🔊" : "🔇");
}
};
button.setToolTipText("");
button.addMouseListener(new MouseAdapter() {
@Override public void mousePressed(MouseEvent e) {
if (!button.isEnabled()) {
slider.setValue(80);
button.setEnabled(true);
}
Component b = (Component) e.getSource();
Dimension d = popup.getPreferredSize();
popup.show(b, (b.getWidth() - d.width) / 2, -d.height);
}
@Override public void mouseEntered(MouseEvent e) {
if (!popup.isVisible()) {
ToolTipManager.sharedInstance().setEnabled(true);
}
}
@Override public void mouseExited(MouseEvent e) {
if (!popup.isVisible()) {
ToolTipManager.sharedInstance().setEnabled(true);
}
}
});
popup.addPopupMenuListener(new PopupMenuListener() {
@Override public void popupMenuCanceled(PopupMenuEvent e) {
/* not needed */
}
@Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
EventQueue.invokeLater(() -> ToolTipManager.sharedInstance().setEnabled(false));
}
@Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
button.setSelected(false);
}
});
View in GitHub: Java, KotlinDescription
JPopupMenu- レイアウトを
BorderLayoutに変更して垂直JSliderをひとつだけ追加 JPopupMenu#addMouseWheelListener(InputEvent::consume)を追加して余白などでマウスホイールを回転しても閉じないよう設定PopupMenuListenerを追加してJPopupMenuが開いたあとはJToolTipを無効化、閉じる前にJToggleButtonの選択状態を解除
- レイアウトを
JSliderMouseWheelListenerを追加してマウスホイールの回転で値を変更可能に設定ChangeListenerを追加して値が0(最小値)になったらJToggleButtonを無効化UIManager.put("Slider.paintValue", Boolean.TRUE)で垂直JSlider上部に値を常時表示
JToggleButtonJToggleButton#setToolTipText("")で空文字(JPopupMenuの幅より短くなる文字)をToolTipTextとして設定JToggleButton#createToolTip()をオーバーライドしJToolTipにHierarchyListenerを追加JToggleButton#getToolTipLocation()をオーバーライドし常にJPopupMenuの背面に表示されるよう位置を調整JToggleButton#setEnabled(...)をオーバーライドし、有効なら🔊、無効なら🔇にテキストを変更JSliderの値が0でJToggleButtonが無効状態でもJToolTipは有効- 無効状態の
JToggleButtonをクリックした場合もJPopupMenuを開くようにするためActionListenerではなくMouseListenerを追加MouseListener#mousePressed(...)でJPopupMenuを開く前にJToggleButtonが無効状態の場合は値をデフォルトの80まで戻す- マウスカーソルが出入りしたとき
JPopupMenuが非表示の場合はJPopupMenuを開くときに無効化したJToolTipを有効に戻す
JToolTip- 追加した
HierarchyListenerでJToolTipの表示後、重ねてJPopupMenuを表示するよう設定JPopupMenuの表示後にJPopupMenuに追加した上記のPopupMenuListener#popupMenuWillBecomeVisible(...)でEventQueue.invokeLater( () -> ToolTipManager.sharedInstance().setEnabled(false))を実行してJToolTipを無効化
- 追加した
Reference
- JSliderの上部に現在値を常時表示する
- JSliderのUIや色を変更する
- WhitespaceAround misrecognizes white spaces after emojis · Issue #10837 · checkstyle/checkstyle
- 「🔊(
U+1F50A)(\uD83D\uDD0A)」などの0x0A(CR/LF)が誤判定されているようで、このサンプルコードでもWhitespaceAroundの警告が発生するがcheckstyle-9.0.2で修正されそう?た
- 「🔊(