如何防止将字符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();
}
}