我想要一种快速使用的方法来输入时间到厘秒。输入数字应从右侧推入并自动添加前导零“。” 和“:”根据需要,例如:
"" => "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;
}
}
}