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