2

時間をセンチ秒単位で入力するための使いやすい方法が必要です。数字を入力すると、数字が右から押し込まれ、自動的に先行ゼロ「.」が追加されます。および必要に応じて ":" を使用します。たとえば、次のようになります。

"" => "0.03" => "0.31" => "3.14" => "31.41" => "3:14.15"

また、「f」を入力すると、「DNF」(「終了しませんでした」) となるはずです: 「3:14.15」 => 「DNF」 => 「0.04」

以下の私のコードは「機能」しますが、常にカーソルが最後に置かれることを除いて (完全に置換されるため)、誰かが途中で編集しようとするとうまくいきません。カーソルをあるべき場所に保つ簡単な方法はありますか? さらに重要なことは、私のアプローチ全体が適切であるか、それとも本当に別の方法で行う必要があるかということです。私は以前に多くの方法 (JFormattedTextField と Formatters、DocumentFilter、DocumentListener など) を試しましたが、ここで同様のことを提案されていたため、それらを機能させることができませんでした。

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;

class TimeField extends JTextField {

  public static void main ( String[] args ) {
    JFrame frame = new JFrame();
    frame.add( new TimeField() );
    frame.add( new TimeField(), BorderLayout.SOUTH );
    frame.pack();
    frame.setDefaultCloseOperation( frame.EXIT_ON_CLOSE );
    frame.setVisible( true );
  }

  TimeField () {
    super( 10 );
    setHorizontalAlignment( RIGHT );
    setFont( new Font( "MONOSPACED", Font.BOLD, 32 ));
    ((AbstractDocument) getDocument()).setDocumentFilter( new DocumentFilter() {
      public void insertString ( DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr ) throws BadLocationException {
        replace( fb, offset, 0, string, attr );
      }
      public void remove ( DocumentFilter.FilterBypass fb, int offset, int length ) throws BadLocationException {
        replace( fb, offset, length, "", null );
      }
      public void replace ( DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs ) throws BadLocationException {
        fb.replace( offset,length, text, attrs );
        if ( text.contains("f") ) {
          fb.replace( 0, getText().length(), "DNF", null );
          return;
        }
        text = getText();                                 // get current text
        text = text.replaceAll( "\\D", "" );              // remove non-digits
        text = text.replaceAll( "^0+", "" );              // remove leading zeros
        while ( text.length() < 3 ) text = "0" + text;    // make at least three digits
        text = text.replaceAll( "(.)(..)$", "$1.$2" );    // add point if necessary
        text = text.replaceAll( "(.)(..\\.)", "$1:$2" );  // add colon if necessary
        fb.replace( 0, getText().length(), text, null );  // replace original with formatted
      }
    } );
  }
}

編集:以前に JFormattedTextField を試しましたが、これが私の最善の試みです。数字を入力できます。フォーカスがフィールドを離れると、valueToString が呼び出され、ポイント + コロンが追加されて表示されます。しかし、これは編集後ではなく、編集中に実行したいと思います。MaskFormatter が明らかにそれを行うことができるので、私は何かが欠けているに違いありません。

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;

class TimeField extends JFormattedTextField {

    public static void main(String[] args) {
       //Create Event Disptach Thread for  swing UI and its components to run on 
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                JFormattedTextField ftf = new JFormattedTextField(new TimeFormatter());
                ftf.setHorizontalAlignment(JTextField.RIGHT);
                ftf.setFont(new Font(Font.MONOSPACED, Font.BOLD, 32));
                ftf.setColumns(10);
                frame.getContentPane().add(ftf);
                frame.getContentPane().add(new JButton("foo"), BorderLayout.SOUTH);
                frame.pack();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }

    static class TimeFormatter extends DefaultFormatter {
        public Object stringToValue(String text) {
            System.out.println("stringToValue(" + text + ")");
            return text == null ? "" : text.replaceAll("\\D", "");
        }
        public String valueToString(Object value) {
            System.out.println("valueToString(" + value + ")");
            return value == null ? null : format((String)value);
        }
        private String format(String text) {
            text = text.replaceAll("\\D", "");              // remove non-digits
            text = text.replaceAll("^0+", "");              // remove leading zeros
            while (text.length() < 3) text = "0" + text;    // make at least three digits
            text = text.replaceAll("(.)(..)$", "$1.$2");    // add point
            text = text.replaceAll("(.)(..\\.)", "$1:$2");  // add colon if necessary
            return text;
        }
    }
}
4

0 に答える 0