JSpinnerの増減ボタンを分離・拡大する
Total: 7, Today: 7, Yesterday: 0
Posted by aterai at
Last-modified:
Summary
JSpinnerにフォーカスが移動したらその増減ボタンをJSpinner本体からJPopupMenuに移動し、クリックが容易になるようボタンサイズを拡大します。
Screenshot

Advertisement
Source Code Examples
class EnlargedButtonSpinner extends JSpinner {
private transient MouseAdapter listener;
protected EnlargedButtonSpinner(SpinnerModel model) {
super(model);
}
@Override public void updateUI() {
JTextField field = ((JSpinner.DefaultEditor) getEditor()).getTextField();
field.removeMouseListener(listener);
super.updateUI();
listener = new ArrowButtonEnlargeListener();
field.addMouseListener(listener);
}
}
class ArrowButtonEnlargeListener extends MouseAdapter {
private final JPopupMenu popup = new JPopupMenu();
@Override public void mousePressed(MouseEvent e) {
Component c = SwingUtilities.getAncestorOfClass(
JSpinner.class, e.getComponent());
if (SwingUtilities.isLeftMouseButton(e) && c instanceof JSpinner) {
JSpinner spinner = (JSpinner) c;
JButton bigNextBtn = makeArrowButton(spinner, true);
JButton bigPrevBtn = makeArrowButton(spinner, false);
popup.setLayout(new GridLayout(2, 1));
popup.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
popup.setFocusable(false);
popup.removeAll();
popup.add(bigNextBtn);
popup.add(bigPrevBtn);
popup.pack();
JComponent editor = spinner.getEditor();
Rectangle r = SwingUtilities.calculateInnerArea(editor, null);
int px = (int) r.getMaxX();
int py = (int) r.getCenterY() - bigNextBtn.getPreferredSize().height;
popup.show(editor, px, py);
}
}
private static JButton makeArrowButton(JSpinner spinner, boolean isNext) {
int direction = isNext ? SwingConstants.NORTH : SwingConstants.SOUTH;
JButton arrowButton = new BasicArrowButton(direction) {
@Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.width *= 4;
d.height *= 2;
return d;
}
};
String name = isNext ? "increment" : "decrement";
ArrowButtonHandler handler = new ArrowButtonHandler(spinner, name, isNext);
arrowButton.addActionListener(handler);
arrowButton.addMouseListener(handler);
return arrowButton;
}
}
View in GitHub: Java, KotlinDescription
JSpinnerの増減ボタンを、たとえばタッチパネルでの操作でもクリックし易くなるよう拡大表示する- 増減ボタンのコピーを
JPopupMenuに配置してJSpinnerとは切り離して表示することでJSpinner本体の高さは変更せず、増減ボタンのサイズのみ拡大する- JSpinnerのArrowButtonのサイズを変更では
JSpinner本体の高さ変更に連動して、増減ボタンの高さを拡大している
- JSpinnerのArrowButtonのサイズを変更では
- コピーした増減ボタンのサイズは
BasicArrowButton#getPreferredSize()をオーバーライドして推奨サイズの幅を4倍、高さを2倍に拡大しているUIManager.getDimension("Spinner.arrowButtonSize")でも増減ボタンのサイズは取得可能だが、NimbusLookAndFeelではnullになってしまう
- 増減ボタンのコピー配置した
JPopupMenuの表示位置はJSpinner#getEditor()で取得したエディタの右端と中央を基準にしているArrowButtonを基準:WindowsLookAndFeelで増減ボタンの名前が設定されていないため増減ボタンを取得しづらいJTextFieldを基準:*1#getTextField()で取得可能なJTextFieldを基準にするとNimbusLookAndFeelで増減ボタンとの間隔が取得しづらい
- コピーした増減ボタンには、
BasicSpinnerUIのArrowButtonHandlerを参考に長押しでクリックを自動繰り返しするリスナーを追加JSpinner.DateEditorのキャレット位置による日時の増減機能は省略している