KeyListener
で正しくレンダリングされない文字列に文字が追加されるのを防ぐ方法はGraphics.drawString()
?
私が防止しようとしているのは、java.atw.Graphics.drawString() で適切にレンダリングされない文字列に追加される java.atw.event.KeyListener フォームの文字です。たとえば、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 = "!@#$%^&*()\\/?<>:;\"\'}{[]`~,.-=+| ";
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();
}
}