创建可撤消的 JTextField

问题描述 投票:0回答:3

我已经实现了一个可撤消的 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) {}
                }
            });
        }    
    }
}
java swing jtextfield undo-redo
3个回答
2
投票

我不是 100% 确定,但我的猜测是您使用的输入映射在窗口中的所有组件之间共享。前两个字段的看跌期权被第三个字段的看跌期权覆盖。

如果我使用

getInputMap()
则撤消似乎可以按文本字段进行。


0
投票

为后代修正代码:

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) {}
            }
       });
    }    
}

0
投票

更新 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) {
                }
            }
        });
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.