Swing/SpinnerMenuItem のバックアップ(No.1)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/SpinnerMenuItem へ行く。
- 1 (2025-01-27 (月) 07:45:32)
- 2 (2025-02-24 (月) 01:30:51)
- category: swing folder: SpinnerMenuItem title: JPopupMenuのMenuItemとしてJSpinnerを配置する tags: [JSpinner, JMenuItem, JPopupMenu, JSlider, LayoutManager] author: aterai pubdate: 2025-01-27T07:43:46+09:00 description: JPopupMenuのMenuItemとしてMenuElementを実装しないJSpinnerやJSliderなどのコンポーネントを使用します。 image: https://drive.google.com/uc?id=1QqtQjPQ5KaFOGQr-RBfKkE-gkwyRmg8r
Summary
JPopupMenuのMenuItemとしてMenuElementを実装しないJSpinnerやJSliderなどのコンポーネントを使用します。
Screenshot

Advertisement
Source Code Examples
private static Component makeSpinnerMenuItem(String title, Component c) {
JMenuItem item = new JMenuItem() {
@Override public void updateUI() {
super.updateUI();
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
setEnabled(false);
setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
}
@Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = Math.max(d.height, c.getPreferredSize().height);
return d;
}
};
item.add(new JLabel(title));
item.add(c);
return item;
}
private static JMenu makeSpinnerMenu() {
SpinnerNumberModel model1 = new SpinnerNumberModel(100, 10, 300, 10);
SpinnerNumberModel model2 = new SpinnerNumberModel(150, 10, 300, 10);
JMenu menu = new JMenu("JSpinner");
menu.add(makeMenuBox("L: ", makeSpinner(model1)));
menu.add(makeMenuBox("R: ", makeSpinner(model2)));
menu.add(new JSeparator());
menu.add(makeSpinnerMenuItem("Left: ", makeSpinner(model1)));
menu.add(makeSpinnerMenuItem("Right: ", makeSpinner(model2)));
menu.addSeparator();
menu.add("JMenuItem1");
menu.add("JMenuItem2");
menu.add(Box.createHorizontalStrut(160));
return menu;
}
private static JSpinner makeSpinner(SpinnerModel model) {
JSpinner spinner = new JSpinner(model);
((JSpinner.DefaultEditor) spinner.getEditor()).getTextField().setColumns(8);
spinner.addMouseWheelListener(e -> {
JSpinner s = (JSpinner) e.getComponent();
SpinnerModel o = s.getModel();
if (s.isEnabled() && o instanceof SpinnerNumberModel) {
SpinnerNumberModel m = (SpinnerNumberModel) o;
m.setValue(m.getNumber().intValue() - e.getWheelRotation());
}
e.consume();
});
return spinner;
}
View in GitHub: Java, KotlinExplanation
JSpinner
メニュー上:Box.createHorizontalBox()
にタイトル表示用のJLabel
とJSpinner
を配置してJMenu#add(...)
でJPopupMenu
に配置MenuElement
を実装しないコンポーネントなので↑キー入力などでのメニュー選択などは不可だが、JSpinner
自体のマウス入力での操作やTabキー入力によるフォーカス移動は可能
JSpinner
メニュー下: 無効化したJMenuItem
のタイトルを空、かつ右寄せのFlowLayout
を設定し、別途タイトル表示用のJLabel
とJSpinner
を配置してJMenu#add(...)
でJPopupMenu
に配置MenuElement
を実装するJMenuItem
なので↑キー入力などでのメニュー選択が可能で、かつJSpinner
自体のマウス入力での操作やTabキー入力によるフォーカス移動も可能- 無効化した
JMenuItem
の選択状態表示はDisabledなJMenuItemのハイライトをテストのようにLookAndFeel
に依存する JSpinner
に追加したMouseWheelListener
でホイール回転による値の変更も可能Java 8
ではJSpinner
やJMenuItem
上でホイールを回転するとJPopupMenu
が閉じてしまうのでJPopupMenuに追加したJSliderの表示・非表示をチェックボックスで切り替えるのようにホイールイベントを消費するMouseWheelListener
を追加する必要があったが、Java 9
では修正されて不要になった
- 無効化した
JMenuItem
でクリックしてもJPopupMenu
を閉じないよう設定するのではなく、選択アイコンを非表示化したJCheckBoxMenuItem
にputClientProperty("CheckBoxMenuItem.doNotCloseOnMouseClick", true)
を設定して使用する方法もJava 9
以降では可能
JSlider
メニュー- 同様に
JSlider
を配置して使用も可能 - JPopupMenuに追加したJSliderの表示・非表示をチェックボックスで切り替える
- 同様に
- 同様に
JButton
を配置して使用も可能 JComboBox
も配置可能だが、ドロップダウンリストが開くとJPopupMenu
が閉じてしまう