0

如何防止将字符KeyListener添加到无法正确呈现的字符串中Graphics.drawString()

我试图阻止的是将 java.atw.event.KeyListener 表单中的字符添加到无法使用 java.atw.Graphics.drawString() 正确呈现的字符串中。例如,如果我按下 shift,我的程序将检测到它是一个无效字符,并且不会将它添加到稍后将呈现 java.atw.Graphics.drawString() 的字符串中。当然我可以检查一下,但有什么简单的方法吗?不是以涉及 1000 个字符检查的方式。

我的程序是对 javax.swing.JTextField 的一个小改造。我已经尝试查看 src 代码,但我找不到任何东西。这是(这可以作为任何摆动组件添加到 Frame 中):

// Lots of imports

public class TextField extends JComponent implements KeyListener, Runnable, MouseInputListener, ClipboardOwner, FocusListener{
private static final long serialVersionUID = 1;

private String text;

private int head = 0;
private int draggedFrom = 0;
private boolean renderHead = false;
private boolean insert = false;
private boolean dragging = false;
private int renderOffset;

private int time = 0;
private int doubleClickTimer = -1;

private boolean editable = true;

private int historyIndex = 0;
private ArrayList<String> history = new ArrayList<String>();

private boolean focus = this.hasFocus();

public TextField() {
    this(null);
}

public TextField(String text){
    this.text = text == null ? "" : text;

    this.addMouseListener(this);
    this.addMouseMotionListener(this);
    this.addKeyListener(this);

    this.addFocusListener(this);
    this.setFocusable(true);

    new Thread(this).start();

    this.setFont(new Font(null, 0, 40));

    this.setDoubleBuffered(false);
    this.setVisible(true);
}

@Override
public void run() {
    try{
        while (focus){
            Thread.sleep(1);

            if (doubleClickTimer != -1){
                doubleClickTimer++;
            }
            if (doubleClickTimer >= 250){
                doubleClickTimer = -1;
            }

            time++;
            if (time == 500){
                time = 0;

                renderHead = !renderHead;

                repaint(10 - renderOffset + (head == 0 ? 0 : this.getFontMetrics(this.getFont()).stringWidth(text.substring(0, head))),
                        this.getHeight() / 2 - this.getFontMetrics(this.getFont()).getHeight() / 2,
                        insert ? 5 : 2, this.getFontMetrics(this.getFont()).getHeight());
            }
        }
    }catch (InterruptedException e){
        e.printStackTrace();
    }
}

@Override
public void paint(Graphics gr) {
    Graphics2D g = (Graphics2D) gr;

    g.clearRect(0, 0, this.getWidth(), this.getHeight());

    if (!editable){
        g.setColor(Color.GRAY);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
    }

    if (text != null){
        g.setFont(this.getFont());
        int height = this.getHeight() / 2 - g.getFontMetrics().getHeight() / 2;
        int width = (head == 0 ? 0 : g.getFontMetrics().stringWidth(text.substring(0, head)));

        if (width - renderOffset > this.getWidth() - 20){
            renderOffset = width - this.getWidth() + 20;
        }else if (renderOffset > width){
            renderOffset = width;
        }else if (renderOffset > 0 && g.getFontMetrics().stringWidth(text) - renderOffset < this.getWidth() - 20){
            renderOffset = g.getFontMetrics().stringWidth(text) - this.getWidth() + 20;
            if (renderOffset < 0){
                renderOffset = 0;
            }
        }

        if (draggedFrom != head && focus){
            g.setColor(new Color (150, 150, 255));
            if (head < draggedFrom){
                g.fillRect(10 - renderOffset + width, height, 
                        g.getFontMetrics().stringWidth(text.substring(head, draggedFrom)) + (insert ? 5 : 2), g.getFontMetrics().getHeight());
            }else{
                g.fillRect(10 - renderOffset + g.getFontMetrics().stringWidth(text.substring(0, draggedFrom)),
                        height, g.getFontMetrics().stringWidth(text.substring(draggedFrom, head)) + (insert ? 5 : 2), g.getFontMetrics().getHeight());
            }
        }

        if (((editable && renderHead) || dragging) && focus){
            g.setColor(Color.BLACK);
            g.fillRect(10 - renderOffset + width, height, insert ? 5 : 2, g.getFontMetrics().getHeight());
        }

        g.setColor(Color.BLACK);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g.drawString(text, 10 - renderOffset, height + g.getFontMetrics().getAscent());
    }
    g.setColor(Color.BLACK);
    g.drawRect(0, 0, this.getWidth() - 1, this.getHeight() - 1);

    g.dispose();
}

@Override
public void keyPressed(KeyEvent e) {
    if (editable){
        time = -1;
        renderHead = true;

        if (e.isControlDown() && (e.getKeyCode() == KeyEvent.VK_Z || e.getKeyCode() == KeyEvent.VK_Y)){
            if (e.getKeyCode() == KeyEvent.VK_Z ? historyIndex > 0 : history.size() > historyIndex + 1){

                if (e.getKeyCode() == KeyEvent.VK_Z){
                    historyIndex--;
                }else{
                    historyIndex++;
                }

                String s = history.get(historyIndex);
                head = s.length();
                draggedFrom = 0;

                if (text.length() > 0 && s.length() > 0 && s.length() > text.length()){
                    while (draggedFrom < Math.min(text.length(), s.length()) && text.charAt(draggedFrom) == s.charAt(draggedFrom)){
                        draggedFrom++;
                    }

                    int textIndex = text.length() - 1;
                    int sIndex = s.length() - 1;

                    while (Math.min(textIndex, sIndex) >= 0 && text.charAt(textIndex) == s.charAt(sIndex)){
                        head--;

                        textIndex--;
                        sIndex--;
                    }
                }else{
                    draggedFrom = head;
                }

                text = s;
                repaint();
            }
            return;
        }else if (e.getKeyCode() == KeyEvent.VK_RIGHT){
            if (head < text.length()){
                head++;
            }
            this.draggedFrom = head;

            repaint();
            return;
        }else if (e.getKeyCode() == KeyEvent.VK_LEFT){
            if (head > 0){
                head--;
            }
            this.draggedFrom = head;

            repaint();
            return;
        }else if (e.getKeyCode() == KeyEvent.VK_INSERT){
            insert = !insert;

            repaint();
            return;
        }else if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_A){
            if (text.length() > 0){
                this.head = text.length();
                this.draggedFrom = 0;
                repaint();
            }
            return;
        }

        if (e.getKeyCode() != KeyEvent.VK_SHIFT && e.getKeyCode() != KeyEvent.VK_CONTROL && e.getKeyCode() != KeyEvent.VK_ALT &&
                e.getKeyCode() != 12 && e.getKeyCode() != KeyEvent.VK_ESCAPE && !e.isActionKey()){
            for (int i = history.size() - 1; i >= historyIndex; i--){
                history.remove(i);
            }

            if (history.size() > 200){
                history.remove(0);
                historyIndex--;
            }

            history.add(text);
            historyIndex++;

            if (history.size() > 1 && history.get(history.size() - 2).equals(history.get(history.size() - 1))){
                history.remove(history.size() - 1);
                historyIndex--;
            }
        }

        if (e.getKeyCode() == KeyEvent.VK_ENTER){
            for (ActionListener a : listenerList.getListeners(ActionListener.class)){
                a.actionPerformed(new ActionEvent(this, 0, text));
            }
        }else if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_C){
            if (draggedFrom != head){
                Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();

                board.setContents(new StringSelection(draggedFrom < head ? text.substring(draggedFrom, head)
                        : text.substring(head, draggedFrom)), this);
            }
        }else if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_V){
            Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();
            if (board.isDataFlavorAvailable(DataFlavor.stringFlavor)){
                try{
                    String clipboard = (String) board.getData(DataFlavor.stringFlavor);
                    if (draggedFrom != head){
                        if (head <= draggedFrom){
                            text = text.substring(0, head) + clipboard + text.substring(draggedFrom);
                            draggedFrom = head;
                            head += clipboard.length();
                        }else{
                            text = text.substring(0, draggedFrom) + clipboard + text.substring(head);
                            head = draggedFrom + clipboard.length();
                        }
                    }else{
                        if (head == text.length()){
                            text += clipboard;
                        }else if (head == 0){
                            text = clipboard + text;
                        }else{
                            text = text.substring(0, head) + clipboard + text.substring(insert ? head + 1 : head, text.length());
                        }
                        draggedFrom = head;
                        head += clipboard.length();
                    }
                }catch (Exception exc){

                }
            }
        }else if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_X){
            if (draggedFrom != head){
                Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard();

                board.setContents(new StringSelection(draggedFrom < head ? text.substring(draggedFrom, head)
                        : text.substring(head, draggedFrom)), this);

                if (head <= draggedFrom){
                    text = text.substring(0, head) + text.substring(draggedFrom);
                }else{
                    text = text.substring(0, draggedFrom) + text.substring(head);
                    head = draggedFrom;
                }

                draggedFrom = head;
            }
        }else if (e.getKeyCode() == KeyEvent.VK_DELETE){
            if (text.length() > 0){
                if (draggedFrom != head){
                    if (head <= draggedFrom){
                        text = text.substring(0, head) + text.substring(draggedFrom);
                    }else{
                        text = text.substring(0, draggedFrom) + text.substring(head);
                        head = draggedFrom;
                    }
                }else if (head == 0){
                    text = text.substring(1);
                }else if (head != text.length()){
                    text = text.substring(0, head) + text.substring(head + 1);
                }
                this.draggedFrom = head;
            }
        }else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE){
            if (draggedFrom != head){
                if (head <= draggedFrom){
                    text = text.substring(0, head) + text.substring(draggedFrom);
                }else{
                    text = text.substring(0, draggedFrom) + text.substring(head);
                    head = draggedFrom;
                }
            }else if (head > 0){
                head--;
                if (head == text.length()){
                    text = text.substring(0, head);
                }else{
                    text = text.substring(0, head) + text.substring(head + 1, text.length());
                }
            }
            this.draggedFrom = head;
        }else if (e.getKeyCode() != KeyEvent.VK_SHIFT && e.getKeyCode() != KeyEvent.VK_CONTROL && e.getKeyCode() != KeyEvent.VK_ALT &&
                e.getKeyCode() != 12 && e.getKeyCode() != KeyEvent.VK_ESCAPE && !e.isActionKey()){
            if (draggedFrom != head){
                if (head <= draggedFrom){
                    text = text.substring(0, head) + e.getKeyChar() + text.substring(draggedFrom);
                    head++;
                }else{
                    text = text.substring(0, draggedFrom) + e.getKeyChar() + text.substring(head);
                    head = draggedFrom + 1;
                }
            }else{
                if (head == text.length()){
                    text += e.getKeyChar();
                }else if (head == 0){
                    text = e.getKeyChar() + (insert ? text.substring(1) : text);
                }else{
                    text = text.substring(0, head) + e.getKeyChar() + text.substring(insert ? head + 1 : head, text.length());
                }
                head++;
            }
            this.draggedFrom = head;
        }

        this.repaint();
    }
}

public void setEditable(boolean editable) {
    if (this.editable != editable){
        this.editable = editable;
        this.repaint();
    }
}

public String getText() {
    return text;
}

public void setText(String text) {
    if (!this.text.equals(text == null ? "" : text)){
        this.text = text == null ? "" : text;
        this.draggedFrom = this.head = this.text.length();

        history.clear();
        historyIndex = 0;

        this.repaint();
    }
}

@Override
public void mouseMoved(MouseEvent e) {
    if (this.getCursor() != Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)){
        this.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
    }
}

@Override
public void mousePressed(MouseEvent e) {
    time = -1;
    renderHead = true;
    draggedFrom = head = this.getHead(e.getX());

    if (doubleClickTimer != -1){
        doubleClickTimer = -1;

         if (head == text.length()){
                draggedFrom = 0;
        }else if (head > 0 && this.isSplitCharacter(text.charAt(head - 1))){
            draggedFrom--;
        }else if (head == 0){
            while (draggedFrom < text.length() && !this.isSplitCharacter(text.charAt(draggedFrom))){
                draggedFrom++;
            }
        }else{
            while (head < text.length() && !this.isSplitCharacter(text.charAt(head))){
                head++;
            }

            while (draggedFrom > 0 && !this.isSplitCharacter(text.charAt(draggedFrom - 1))){
                draggedFrom--;
            }
        }
    }else{          
        doubleClickTimer = 0;
    }


    this.repaint();

    this.requestFocusInWindow();
}

private boolean isSplitCharacter (char c){
    final String splitCharacters = "!@#$%^&*()\\/?<>:;\"\'}{[]`~,.-=+| ";

    for (char a : splitCharacters.toCharArray()){
        if (a == c) return true;
    }

    return false;
}

@Override
public void mouseReleased(MouseEvent e) {
    dragging = false;
}

@Override
public void setFont(Font font) {
    super.setFont(font);
    this.repaint();
}

@Override
public void mouseDragged(MouseEvent e) {
    doubleClickTimer = -1;
    dragging = true;

    int newPlace = this.getHead(e.getX());

    if (head != newPlace){
        head = newPlace;
        this.repaint();
    }
}

private int getHead(int x){
    x += renderOffset - 7;
    if (text.length() != 0){
        for (int i = 1; i <= text.length(); i++){
            if (x <= this.getFontMetrics(this.getFont()).stringWidth(text.substring(0, i))
                    - this.getFontMetrics(this.getFont()).stringWidth(text.substring(i - 1, i)) / 2){
                return i - 1;
            }
        }
    }

    return text.length();
}

public void addActionListener(ActionListener e) {
    this.listenerList.add(ActionListener.class, e);
}

public void removeActionListener(ActionListener e){
    this.listenerList.remove(ActionListener.class, e);
}

public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void lostOwnership(Clipboard clipboard, Transferable contents) {}

@Override
public void focusGained(FocusEvent e) {
    this.renderHead = true;
    this.time = 0;

    focus = true;
    new Thread(this).start();

    repaint();
}

@Override
public void focusLost(FocusEvent e) {
    this.renderHead = false;
    this.time = 0;

    focus = false;

        repaint();
    }
}
4

1 回答 1

1

监听keyTyped事件以确定可以显示哪些字符。

于 2013-06-08T01:48:35.003 回答