Để xử lý bài này thì bạn nên dùng state machine, cách clean và robust nhất là bạn dùng DFA (Deterministic Finite Automaton) cho thằng formatter, rồi xử lý theo. Mặc dù làm cách này thủ công, nhưng bạn có full-control.
Mình làm nháp sơ, ý tưởng của mình tương tự như trên nhưng mình chỉ làm sơ xài thôi. Bạn nên test lại cẩn thận rồi mới nên đưa vào production. Ý tưởng của mình là tạo 2 buffer, một thằng cho integer, một thằng cho decimal, tùy vào giá trị nhập vào mà mình xử lý. Máy này mình không có Android, nên mình dùng tạm thằng JTextField với KeyListener, làm với Android thì nó tương ứng với EditText và TextWatcher, cụ thể:
Mã:
afterTextChanged = keyReleaseonTextChange = keyTyped
MyApp.java
Mã:
import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.text.DecimalFormat; import javax.swing.JEditorPane;import javax.swing.JPanel;import javax.swing.JTextField; public class MyApp extends JPanel { enum FormatTypingMode { Integer, Decimal, Empty } private JTextField mTextField; /** * Constructor */ public MyApp() { mTextField = new JTextField(20); mTextField.addKeyListener(new FormatDecimalListener()); add(mTextField); } /** * KeyEvent for JTextFieldc */ private class FormatDecimalListener implements KeyListener { /* * The pattern */ private static final String pattern = "###,###.###"; /* * Formatter */ private DecimalFormat formatter; /* * Buffer holding digits of integer part */ private StringBuilder integerBuffer; /* * Buffer holding digits of decimal part */ private StringBuilder decimalBuffer; /* * Current typing mode */ private FormatTypingMode mode; /** * Constructor */ public FormatDecimalListener() { mode = FormatTypingMode.Empty; integerBuffer = new StringBuilder(); decimalBuffer = new StringBuilder(); formatter = new DecimalFormat(pattern); } /** * Calculate double value of both buffers * @return a double */ private double getDoubleValue() { double integer = 0; double decimal = 0; try { integer = Double.parseDouble(integerBuffer.toString()); decimal = Double.parseDouble("0." + decimalBuffer.toString()); } catch (NumberFormatException e) { // handle error } return integer + decimal; } /** * Calculate value of integer buffer * @return an integer */ private int getIntegerValue() { int integer = 0; try { integer = Integer.parseInt(integerBuffer.toString()); } catch (NumberFormatException e) { // handle error } return integer; } /** * Modify mode and buffer when a digit is entered * @param d * a digit [0, 9] */ private void handleDigit(char d) { if (mode == FormatTypingMode.Integer) { integerBuffer.append(d); } else if (mode == FormatTypingMode.Decimal){ decimalBuffer.append(d); } } /** * Modify mode and buffer when a backspace is entered */ private void handleBackspace() { if (mode == FormatTypingMode.Integer) { if (integerBuffer.length() == 0) { mode = FormatTypingMode.Empty; } else { integerBuffer.deleteCharAt(integerBuffer.length() - 1); } } else if (mode == FormatTypingMode.Decimal) { if (decimalBuffer.length() == 0) { mode = FormatTypingMode.Integer; } else { decimalBuffer.deleteCharAt(decimalBuffer.length() - 1); } } else { mode = FormatTypingMode.Empty; } } @Override public void keyPressed(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { if (mode == FormatTypingMode.Integer) { mTextField.setText(formatter.format(getIntegerValue())); } else if (mode == FormatTypingMode.Decimal){ if (!decimalBuffer.toString().equals("")) { mTextField.setText(formatter.format(getDoubleValue())); } else { mTextField.setText(formatter.format(getIntegerValue()) + "."); } } else { // both buffer are empty, do nothing } } @Override public void keyTyped(KeyEvent e) { // start getting input if (mode == FormatTypingMode.Empty && integerBuffer.length() == 0 && decimalBuffer.length() == 0) { mode = FormatTypingMode.Integer; } char c = e.getKeyChar(); if (c == '.') { mode = FormatTypingMode.Decimal; } else if (c >= '0' && c <= '9') { handleDigit(c); } else if (c == KeyEvent.VK_BACK_SPACE) { handleBackspace(); } } }}
Main.java
Mã:
import java.text.DecimalFormat;import java.util.*;import java.awt.*;import java.awt.event.KeyEvent;import java.awt.event.KeyListener; import javax.swing.JFrame;import javax.swing.JTextField; public class Main { public static void main(String[] args) { JFrame frame = new JFrame("Text state machine"); frame.setSize(400, 100); frame.setResizable(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(new MyApp()); frame.setVisible(true); }}
Lưu ý: mình không có handle overflow
Pallet nhựa Long An đã trở thành một trong những lựa chọn phổ biến cho nhu cầu vận chuyển và lưu trữ hàng hóa trong nhiều ngành công nghiệp. Với đặc tính nhẹ nhàng, chắc chắn và dễ vận chuyển, các...
Thanh lý pallet nhựa Long An giá rẻ