• category: swing folder: TimePicker title: JFormattedTextFieldと増減用JButtonを組み合わせて時間選択コンポーネントを作成する title-en: Create a time selection component by combining a JFormattedTextField and increment/decrement JButtons tags: [JFormattedTextField, JButton, JSpinner, Calendar] author: aterai pubdate: 2026-03-02T00:36:33+09:00 description: JFormattedTextFieldの上下に増減用JButtonを配置してJSpinner風の時間選択コンポーネントを作成します。 summary-jp: JFormattedTextFieldの上下に増減用JButtonを配置してJSpinner風の時間選択コンポーネントを作成します。 summary-en: Create a JSpinner-style time selection component by placing increment/decrement JButtons above and below a JFormattedTextField. image: https://drive.google.com/uc?id=101CyjRPsRjX22GM-lMU-HvIAXJ5TBezd

Summary

JFormattedTextFieldの上下に増減用JButtonを配置してJSpinner風の時間選択コンポーネントを作成します。

Source Code Examples

class AutoRepeatHandler extends MouseAdapter implements ActionListener {
  private final Timer autoRepeatTimer;
  private final JTextComponent view;
  private final int delta;
  private final int min;
  private final int max;
  private JButton arrowButton;

  protected AutoRepeatHandler(JTextComponent view, int delta, int min, int max) {
    super();
    this.view = view;
    this.delta = delta;
    this.min = min;
    this.max = max;
    autoRepeatTimer = new Timer(60, this);
    autoRepeatTimer.setInitialDelay(300);
  }

  public static void adjust(JTextComponent field, int delta, int min, int max) {
    field.requestFocusInWindow();
    int range = max - min + 1;
    int value = Integer.parseInt(field.getText());
    value = (value - min + delta) % range;
    if (value < 0) {
      value += range;
    }
    value += min;
    field.setText(String.format("%02d", value));
  }

  @Override public void actionPerformed(ActionEvent e) {
    Object o = e.getSource();
    if (o instanceof Timer) {
      boolean released = Objects.nonNull(arrowButton) &&
                         !arrowButton.getModel().isPressed();
      if (released && autoRepeatTimer.isRunning()) {
        autoRepeatTimer.stop();
      }
    } else if (o instanceof JButton) {
      arrowButton = (JButton) o;
    }
    adjust(view, delta, min, max);
  }

  @Override public void mousePressed(MouseEvent e) {
    if (SwingUtilities.isLeftMouseButton(e) && e.getComponent().isEnabled()) {
      autoRepeatTimer.start();
    }
  }

  @Override public void mouseReleased(MouseEvent e) {
    autoRepeatTimer.stop();
  }

  @Override public void mouseExited(MouseEvent e) {
    if (autoRepeatTimer.isRunning()) {
      autoRepeatTimer.stop();
    }
  }
}
View in GitHub: Java, Kotlin

Description

  • 左: JFormattedTextField+LocalTimeを使用した時間選択コンポーネント
    • new MaskFormatter("##:##")で作成しまマスクをJFormattedTextFieldに設定
    • キー入力での数値変更はJFormattedTextField#setEditable(false)不可で、マウスホイールによる時間変更のみ可能
    • 以下のように:で区切られた時、分フィールド上でマウスホイールが回転したかをチェックして時間を更新
timeField.addMouseWheelListener(e -> {
  boolean isUp = e.getWheelRotation() < 0;
  boolean isHourSide = timeField.viewToModel(e.getPoint()) <= 2;
  adjustTime(isHourSide, isUp);
});
  • 右: JFormattedTextField+JButtonを組み合わせた時間選択コンポーネント
    • 増減ボタンの配置を上下に変更したJSpinner風の時間選択コンポーネント(24時間選択固定)をJFormattedTextField+JButtonで作成
    • 時、分フィールドに別々のJFormattedTextFieldを適用し、増減ボタンもそれぞれの上下に配置して倍の4個使用
    • MouseWheelListenerもそれぞれ設定するので、時、分フィールドのどちらでマウスホイールが回転したかをチェックする必要がない
    • 時、分フィールドは単独でループするよう設定
      • たとえば12:59から分フィールドで1増加しても13:00ではなく12:00に変化する

Reference

Comment