Search code examples
javahexjtextfieldformatterjformattedtextfield

Java Hex Formatter


I need a JTextField to insert hexadecimal bytes. Example: "05 DE DD A9 4D 00 0C 5E" I have tried JFormattedTextField + MaskFormatter with Mask "HH HH HH" but this is a fixed mask. I need one, which could be "filled".

I have also tried the DocumentFilter, but this does not allow me to edit the complete text. Only the inserted chunks were "filtered".

Do you know another way to solve the problem?


Solution

  • Problem solved.

    import java.awt.EventQueue;
    import java.awt.Toolkit;
    
    import javax.xml.bind.DatatypeConverter;
    
    import javax.swing.*;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    
    public class HexTextField extends JTextField implements DocumentListener
    {
        private static final long serialVersionUID= -6694532039668603522L;
        private boolean filtering= false;
    
        public HexTextField()
        {
            super();
            getDocument().addDocumentListener(this);
        }
    
        @Override
        public void changedUpdate(DocumentEvent e)
        {
            filterText();
        }
    
        @Override
        public void insertUpdate(DocumentEvent e)
        {
            filterText();
        }
    
        @Override
        public void removeUpdate(DocumentEvent e)
        {
            filterText();
        }
    
        private void filterText()
        {
            if(filtering)
                return;
            filtering= true;
    
            EventQueue.invokeLater(new Runnable()
            {
                @Override
                public void run()
                {
                    String input= getText().toUpperCase();
                    String filtered= "";
                    int index= 0;
    
                    // filter
                    for(int i= 0; i < input.length(); i++)
                    {
                        char c= input.charAt(i);
                        if("0123456789ABCDEF".indexOf(c) >= 0)  // hex only
                        {
                            filtered+= c;
                            if(index++ % 2 == 1 && i != input.length() - 1)
                                filtered+= " "; // whitespace after each byte
                        }
                    }
    
                    // limit size
                    int maxBytes= 256;
                    if(filtered.length() > 3 * maxBytes)
                    {
                        filtered= filtered.substring(0, 3 * maxBytes);
                        Toolkit.getDefaultToolkit().beep();
                    }
    
                    setText(filtered);
                    filtering= false;
                }
            });
        }
    
        public byte[] getBytes()
        {
            String text= getText().replace(" ", "");
            if(text.length() == 0)
                return null;
    
            if(text.length() % 2 == 1)
                text= text.substring(0, text.length()-1) + "0" + text.charAt(text.length()-1);
    
            byte[] bytes= DatatypeConverter.parseHexBinary(text);
            if(bytes.length == 0)
                return null;
    
            return bytes;
        }
    }