我已经实现了一个可撤消的 JTextField,问题是当我创建多个 JTextField 时,它只是撤消创建的最后一个实例。代码如下 - 要复制,请在第三个字段中输入一些文本,然后在第一个文本字段中输入一些代码,然后键入 ctrl-z 进行撤消 - 它只会从第三个文本字段中删除文本。谁能看到我做错了什么吗?
import java.awt.BorderLayout;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
public class UndoableTextFieldTest
{
public static void main(String... s)
{
new UndoableTextFieldTest();
}
public UndoableTextFieldTest()
{
JFrame frame = new JFrame("UndoableTextFieldTest");
UndoableTextField f1 = new UndoableTextField();
UndoableTextField f2 = new UndoableTextField();
UndoableTextField f3 = new UndoableTextField();
frame.setLayout(new BorderLayout());
frame.getContentPane().add(f1, BorderLayout.NORTH);
frame.getContentPane().add(f2, BorderLayout.CENTER);
frame.getContentPane().add(f3, BorderLayout.SOUTH);
frame.setSize(360, 115);
frame.setVisible(true);
}
public class UndoableTextField extends JTextField
{
KeyStroke undoKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK);
KeyStroke redoKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK);
public UndoableTextField()
{
UndoManager undoManager = new UndoManager();
getDocument().addUndoableEditListener(new UndoableEditListener()
{
@Override
public void undoableEditHappened(UndoableEditEvent e)
{
undoManager.addEdit(e.getEdit());
}
});
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(undoKeyStroke, "undoKeyStroke");
getActionMap().put("undoKeyStroke", new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
undoManager.undo();
} catch (CannotUndoException cue) {}
}
});
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(redoKeyStroke, "redoKeyStroke");
getActionMap().put("redoKeyStroke", new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
undoManager.redo();
} catch (CannotRedoException cre) {}
}
});
}
}
}
我不是 100% 确定,但我的猜测是您使用的输入映射在窗口中的所有组件之间共享。前两个字段的看跌期权被第三个字段的看跌期权覆盖。
如果我使用
getInputMap()
则撤消似乎可以按文本字段进行。
为后代修正代码:
import java.awt.BorderLayout;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
public class UndoableTextFieldTest
{
public static void main(String... s)
{
new UndoableTextFieldTest();
}
public UndoableTextFieldTest()
{
KeyStroke undoKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK);
KeyStroke redoKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK);
public UndoableJTextField()
{
UndoManager undoManager = new UndoManager();
getDocument().addUndoableEditListener(new UndoableEditListener()
{
@Override
public void undoableEditHappened(UndoableEditEvent e)
{
undoManager.addEdit(e.getEdit());
}
});
getInputMap().put(undoKeyStroke, "undoKeyStroke");
getActionMap().put("undoKeyStroke", new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
try { undoManager.undo(); }
catch (CannotUndoException cue) {}
}
});
getInputMap().put(redoKeyStroke, "redoKeyStroke");
getActionMap().put("redoKeyStroke", new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
try { undoManager.redo(); }
catch (CannotRedoException cre) {}
}
});
}
}
更新 UndoableJTextField 类以避免一些编译器警告 (jdk21)。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.undo.*;
public class UndoableTextField extends JTextField {
KeyStroke undoKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
InputEvent.CTRL_DOWN_MASK);
KeyStroke redoKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y,
InputEvent.CTRL_DOWN_MASK);
public UndoableTextField() {
UndoManager undoManager = new UndoManager();
getDocument().addUndoableEditListener(new UndoableEditListener() {
@Override
public void undoableEditHappened(UndoableEditEvent e) {
undoManager.addEdit(e.getEdit());
}
});
getInputMap().put(undoKeyStroke, "undoKeyStroke");
getActionMap().put("undoKeyStroke", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
try {
undoManager.undo();
}
catch (CannotUndoException cue) {
}
}
});
getInputMap().put(redoKeyStroke, "redoKeyStroke");
getActionMap().put("redoKeyStroke", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
try {
undoManager.redo();
}
catch (CannotRedoException cre) {
}
}
});
}
}