基於Document機制的Swing IP地址控件

//import 標準JDK,在Eclipse裏面使用Ctrl+Shift+I進行import


/**
 * IP地址文本框.<br/>
 * 可隨意複製粘貼
 *
 * @author [email protected] 2014-8-6
 */
public class IPAddressArea extends JTextField
{

    private static final long serialVersionUID = -1738690267989023760L;


    /**
     * 字符的正則表達式
     */
    public static final String AbsRegx = "[0-9a-zA-Z]+";

    /**
     * IP地址的正則表達式
     */
    public final static String IPREGEX = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
            + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
            + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";


    public inal Border lineBorder = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);

    public inal Border emptyBorder = BorderFactory.createEmptyBorder();


    private class IPAddressDocument extends PlainDocument
    {
        private static final long serialVersionUID = 2508417082430336855L;

        @Override
        public void insertString(int offs, final String str, final AttributeSet a) throws BadLocationException
        {
            if (offs > 15)
            {
                Toolkit.getDefaultToolkit().beep();
                return;
            }
            String text = IPAddressArea.this.getText();
            // 原始內容爲空則直接輸入,前提條件由setText保證
            if (text.isEmpty())
            {
                super.insertString(offs, str, a);
                return;
            }
            String[] ips = text.split("\\.", -1);
            if (str.length() == 1)
            {
                // 允許輸入 , . 用於左移位和右移位
                if (str.charAt(0) == '.')
                {
                    if (offs >= text.length())
                    {
                        // 右移到末尾後跳到首位
                        IPAddressArea.this.setCaretPosition(0);
                    }
                    else
                    {
                        IPAddressArea.this.setCaretPosition(offs + 1);
                    }
                    return;
                }

                if (str.charAt(0) == ',')
                {
                    if (offs < 1)
                    {
                        //右移位到首位後跳到末尾
                        IPAddressArea.this.setCaretPosition(text.length());
                    }
                    else
                    {
                        IPAddressArea.this.setCaretPosition(offs - 1);
                    }
                    return;
                }

                if (!str.matches(DigitRegx))
                {
                    // 不允許輸入非數字字符
                    Toolkit.getDefaultToolkit().beep();
                    return;
                }

                // 分四段進行處理
                if (offs <= ips[0].length())
                {
                    this.insertIPSegment(offs, str, a, ips[0], 0);
                    return;
                }
                else if (offs <= (ips[0].length() + 1 + ips[1].length()))
                {
                    this.insertIPSegment(offs, str, a, ips[1], ips[0].length() + 1);
                    return;
                }
                else if (offs <= (ips[0].length() + 1 + ips[1].length() + 1 + ips[2].length()))
                {
                    this.insertIPSegment(offs, str, a, ips[2], ips[0].length() + 1 + ips[1].length() + 1);
                    return;
                }
                else if (offs <= (ips[0].length() + 1 + ips[1].length() + 1 + ips[2].length() + 1 + ips[3].length()))
                {
                    this.insertIPSegment(offs, str, a, ips[3],
                            ips[0].length() + 1 + ips[1].length() + 1 + ips[2].length() + 1);
                    return;
                }
                else
                {
                    Toolkit.getDefaultToolkit().beep();
                    return;
                }
            }

            // 一個字符一個字符輸入以簡化處理
            for (int i = 0, len = str.length(); i < len; i++)
            {
                if (str.charAt(i) == '.')
                {
                    continue;
                }
                this.insertString(offs + i, str.charAt(i) + "", a);
            }
        }

        private void insertIPSegment(int offs, final String str, final AttributeSet a, String ipSeg, int startPos)
                throws BadLocationException
        {
            // 針對IP地址的每一段的四個可能的位置進行處理
            if (offs - startPos == 0)
            {
                String s1 = str + ipSeg;
                if (Integer.parseInt(s1) > 255)
                {
                    String s2 = str + ipSeg.substring(1);
                    if (Integer.parseInt(s2) <= 255)
                    {
                        if (s2.length() > 3)
                        {
                            IPAddressArea.this.setCaretPosition(IPAddressArea.this.getCaretPosition() + 1);
                            this.insertString(offs + 1, str, a);
                        }
                        else
                        {
                            super.remove(0 + startPos, 1);
                            super.insertString(0 + startPos, str, a);
                        }
                        return;
                    }
                    Toolkit.getDefaultToolkit().beep();
                    return;
                }
                if (s1.length() > 3)
                {
                    IPAddressArea.this.setCaretPosition(IPAddressArea.this.getCaretPosition() + 1);
                    this.insertString(offs + 1, str, a);
                }
                else
                {
                    super.insertString(offs, str, a);
                }
            }
            else if (offs - startPos == 1)
            {
                String s1 = ipSeg.charAt(0) + str + ipSeg.substring(1);
                if (Integer.parseInt(s1) > 255)
                {
                    String s2 = ipSeg.charAt(0) + str + ipSeg.substring(2);
                    if (Integer.parseInt(s2) <= 255)
                    {
                        if (s2.length() > 3)
                        {
                            IPAddressArea.this.setCaretPosition(IPAddressArea.this.getCaretPosition() + 1);
                            this.insertString(offs + 1, str, a);
                        }
                        else
                        {
                            super.remove(1 + startPos, 1);
                            super.insertString(1 + startPos, str, a);
                        }
                        return;
                    }
                    Toolkit.getDefaultToolkit().beep();
                    return;
                }

                if (s1.length() > 3)
                {
                    IPAddressArea.this.setCaretPosition(IPAddressArea.this.getCaretPosition() + 1);
                    this.insertString(offs + 1, str, a);
                }
                else
                {
                    super.insertString(offs, str, a);
                }
            }
            else if (offs - startPos == 2)
            {
                String s1 = ipSeg.charAt(0) + "" + ipSeg.charAt(1) + str + ipSeg.substring(2);
                if (Integer.parseInt(s1) > 255)
                {
                    String s2 = ipSeg.charAt(0) + "" + ipSeg.charAt(1) + str;
                    if (Integer.parseInt(s2) <= 255)
                    {
                        if (s2.length() > 3)
                        {
                            IPAddressArea.this.setCaretPosition(IPAddressArea.this.getCaretPosition() + 1);
                            this.insertString(offs + 1, str, a);
                        }
                        else
                        {
                            super.remove(2 + startPos, 1);
                            super.insertString(2 + startPos, str, a);
                        }
                        return;
                    }
                    Toolkit.getDefaultToolkit().beep();
                    return;
                }
                if (s1.length() > 3)
                {
                    IPAddressArea.this.setCaretPosition(IPAddressArea.this.getCaretPosition() + 1);
                    this.insertString(offs + 1, str, a);
                }
                else
                {
                    super.insertString(offs, str, a);
                }
            }
            else
            {
                if (offs >= IPAddressArea.this.getText().length())
                {
                    Toolkit.getDefaultToolkit().beep();
                    return;
                }

                IPAddressArea.this.setCaretPosition(IPAddressArea.this.getCaretPosition() + 1);
                this.insertString(offs + 1, str, a);
            }
        }

        @Override
        public void remove(final int offs, final int len) throws BadLocationException
        {
            String text = IPAddressArea.this.getText();

            // (全選刪除的情況)無論怎麼刪除都保留 ...
            if (text.length() < 3)
            {
                Toolkit.getDefaultToolkit().beep();
                return;
            }

            if (len == 1)
            {
                // 處理異常
                if (text.split("\\.", -1).length > 4)
                {
                    super.remove(offs, len);
                    return;
                }
                // 刪除單個字符,保留 .
                if (text.charAt(offs) != '.')
                {
                    super.remove(offs, len);
                    return;
                }

                if (offs >= 0)
                {
                    // 按退格鍵時光標左移一位
                    IPAddressArea.this.setCaretPosition(offs);
                    return;
                }

                Toolkit.getDefaultToolkit().beep();
                return;
            }

            // 選中多個字符進行刪除
            String substr = text.substring(offs, offs + len);
            // 按照 . 分割,一段一段進行刪除,保留 .
            String[] substrs = substr.split("\\.", -1);
            int length = len;
            for (int i = substrs.length - 1; i >= 0; i--)
            {
                length = length - substrs[i].length();
                super.remove(offs + length, substrs[i].length());
                // 保留小數點
                length--;
            }
            IPAddressArea.this.setCaretPosition(offs);
        }
    }

    /**
     * 判斷是否爲合法IP
     *
     * @return the ip
     */
    public final static boolean isIPAddress(final String ipAddress)
    {
        // String ip = "((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
        // Pattern pattern = Pattern.compile(ip);
        // Matcher matcher = pattern.matcher(ipAddress);
        // return matcher.matches();

        return ipAddress.matches(IPREGEX);
    }

    public final boolean isIPAddress()
    {
        return isIPAddress(this.getText());
    }

    public static void main(final String[] args)
    {
        javax.swing.JFrame frame = new javax.swing.JFrame("JIPAddressField Demo");

        frame.setSize(300, 100);
        frame.setLocation(600, 400);
        frame.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        frame.getContentPane().setLayout(new java.awt.FlowLayout());

        IPAddressArea test = new IPAddressArea();
        test.setText("192.168.0.1");
        // IPAddressArea test2 = new IPAddressArea();
        // IPAddressArea test3 = new IPAddressArea();
        frame.getContentPane().add(test);
        // frame.getContentPane().add(test2);
        // frame.getContentPane().add(test3);
        frame.setVisible(true);
    }

    public JPopupMenu popupMenu = new JPopupMenu();

    private final Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

    /**
     * 使用默認的參數進行構造行數 構造方法
     */
    public IPAddressArea()
    {
        this.enableInputMethods(false);
        this.setText("...");
        this.setDocument(new IPAddressDocument());
        // this.setBounds(0, 0, 200, 50);
        int width = 150, height = 25;
        this.setSize(width, height);
        Dimension size = new Dimension(width, height);
        this.setMinimumSize(size);
        this.setPreferredSize(size);
        this.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
        this.initTextPopupMenu();
    }

    /**
     *
     * 獲得IP地址,僅限與內部使用.<br/>
     * 組裝成一串數據
     *
     */
    public String getIpAddress()
    {
        String ip = this.getText();
        if (IPAddressArea.isIPAddress(ip))
        {
            String[] ips = ip.split("\\.", -1);
            ip = "";
            for (String s : ips)
            {
                ip = "." + s;
            }
            return ip.substring(1);
        }

        return "";
    }

    private void initTextPopupMenu()
    {
        this.setBorder(lineBorder);
        JMenuItem copyMenuItem = new JMenuItem("複製(C)");
        copyMenuItem.setMnemonic(KeyEvent.VK_C);
        copyMenuItem.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(final ActionEvent e)
            {
                StringSelection ssel = new StringSelection(IPAddressArea.this.getText());
                systemClipboard.setContents(ssel, ssel);

            }
        });
        JMenuItem pasteMenuItem = new JMenuItem("粘貼(V)");
        pasteMenuItem.setMnemonic(KeyEvent.VK_V);
        pasteMenuItem.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(final ActionEvent e)
            {
                String str = null;
                try
                {
                    str = (String) (systemClipboard.getContents(this).getTransferData(DataFlavor.stringFlavor));
                }
                catch (Exception e1)
                {
                    e1.printStackTrace();
                }
                IPAddressArea.this.setText(str);
            }
        });

        this.popupMenu.add(copyMenuItem);
        this.popupMenu.add(pasteMenuItem);

        this.popupMenu.setBorder(lineBorder);
        this.popupMenu.setOpaque(true);

        initMouseInputListener(this, this.popupMenu, false);
        this.addKeyListener(new KeyAdapter()
        {
            @Override
            public void keyReleased(final KeyEvent keyevent)
            {
                if (keyevent.getKeyCode() == KeyEvent.VK_CONTEXT_MENU)
                {
                    Rectangle rec = null;
                    try
                    {
                        rec = IPAddressArea.this.modelToView(IPAddressArea.this.getCaretPosition());
                    }
                    catch (BadLocationException e)
                    {
                        e.printStackTrace();
                    }

                    IPAddressArea.this.popupMenu.show(IPAddressArea.this, rec.x, IPAddressArea.this.getHeight() / 2);
                }
            }
        });
    }

    /**
     *
     * 設置IP地址.
     *
     * @see javax.swing.text.JTextComponent#setText(java.lang.String)
     */
    @Override
    public void setText(final String ip)
    {
        if (IPAddressArea.isIPAddress(ip))
        {
            super.setText(ip);
        }
        else
        {
            super.setText("0.0.0.0");
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章