2013-06-08 2 views
0

Как предотвратить добавление символов из KeyListener в строку, которая не будет правильно отображаться с помощью Graphics.drawString()?Предотвращать добавление символов из KeyListener в строку

То, что я пытаюсь предотвратить, - это символы формы java.atw.event.KeyListener, добавляемые к строке, которая не будет правильно отображаться с помощью java.atw.Graphics.drawString(). Например, если я нажимаю shift, моя программа обнаружит, что это недопустимый символ, а не добавляет его в строку, которая позже будет отображаться java.atw.Graphics.drawString(). Конечно, я могу сделать чек на это, но есть ли простой способ сделать это? Не таким образом, который включает в себя 1000 проверок персонажей.

Моя программа представляет собой небольшой римейк javax.swing.JTextField. Я пробовал смотреть на код src для этого, но я ничего не мог найти. Вот это (это может быть добавлен к раме, как любой свинг компонент):

// 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 = "[email protected]#$%^&*()\\/?<>:;\"\'}{[]`~,.-=+| "; 

    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(); 
    } 
} 
+0

Uh, объект GUI, реализующий «Runnable»? – fge

+0

Это для любых вещей, связанных с таймером. Я мог бы использовать java.util.Timer, но это все равно заканчивается использованием Runnable. –

ответ

1

Прислушайтесь keyTyped событий, чтобы определить, которые могут быть отображены символы.

+0

Это не работает для всего. Если вы сделаете ctrl + любой ключ, это приведет к «недопустимому» символу. –

+0

@AlexOrzechowski. Не использовал бы метод getKeyChar() для сравнения с KeyEvent.CHAR_UNDEFINED, чтобы убедиться, что у вас есть действительный символ? – camickr