JPopupMenuのMenuItemとしてJSpinnerを配置する
Total: 97
, Today: 1
, Yesterday: 2
Posted by aterai at
Last-modified:
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
を無効化したJMenuItem
に配置して使用も可能 - マウスクリックは無効でマウスドラッグのみ可能な
JLabel
を配置することも可能 JComboBox
も配置可能だがJComboBox
のドロップダウンリストが開くとその親のJPopupMenu
が閉じてしまうJMenuItem
の代わりにJScrollPane
にJList
を配置してスクロール可能なメニューにすることも可能
Reference
- JPopupMenuのレイアウトを変更して上部にメニューボタンを追加する
- JPopupMenuに追加したJSliderの表示・非表示をチェックボックスで切り替える
- JPopupMenuにマウスドラッグで位置変更を可能にするヘッダを追加する
- JMenuのJPopupMenuにスクロール可能なJListを配置する