Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在JTextField和setText中撤消_Java_Swing_Jtextfield_Settext_Undo Redo - Fatal编程技术网

Java 在JTextField和setText中撤消

Java 在JTextField和setText中撤消,java,swing,jtextfield,settext,undo-redo,Java,Swing,Jtextfield,Settext,Undo Redo,JTextField具有现成的撤销支持。它对用户交互很有效,但不幸的是,如果调用方法setText(stringstr),将导致两次而不是一次可撤消的编辑。因此,此代码看起来和感觉都很好,但不起作用: UndoManager undoManager = new UndoManager(); JTextField tf = new JTextField(); tf.setText("initial value"); tf.getDocument().addUndoableEditListener(

JTextField具有现成的撤销支持。它对用户交互很有效,但不幸的是,如果调用方法setText(stringstr),将导致两次而不是一次可撤消的编辑。因此,此代码看起来和感觉都很好,但不起作用:

UndoManager undoManager = new UndoManager();
JTextField tf = new JTextField();
tf.setText("initial value");
tf.getDocument().addUndoableEditListener(undoManager);
tf.setText("new value");
undoManager.undo();
System.out.println(tf.getText()); // Prints empty string
undoManager.undo();
System.out.println(tf.getText()); // Prints "initial value" as expected

JTextField是否可以将setText()作为唯一一个可撤消的编辑处理?

不支持
dragandrop
UndoAndRedo

必须将数据加载到
UndoManager
并定义
UndoAction UndoAction=new UndoAction()对于简单的
图形
或e.i

   class UndoHandler implements UndoableEditListener {

        @Override
        public void undoableEditHappened(UndoableEditEvent e) {
            undoManager.addEdit(e.getEdit());
            undoAction.update();
        }
    }
并创建
Swing动作
(添加到
JButton)
以将内容刷新回
JTextField

    class UndoAction extends AbstractAction {

        private static final long serialVersionUID = 1L;

        UndoAction() {
            super("Undo");
            setEnabled(false);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            try {
                undo.undo();
            } catch (CannotUndoException ex) {
                System.out.println("Unable to undo: " + ex);
                ex.printStackTrace();
            }
            update();
        }

        protected void update() {
            if (undo.canUndo()) {
                setEnabled(true);
                putValue(Action.NAME, undo.getUndoPresentationName());
            } else {
                setEnabled(false);
                putValue(Action.NAME, "Undo");
            }
        }
   } 
找到了一个解决方法:

public class SetTextEditUndo extends AbstractUndoableEdit {

    public JTextField src;
    public String oldValue;
    public String newValue;

    public SetTextEditUndo(JTextField src, String oldValue, String newValue) {
        this.src = src;
        this.oldValue = oldValue;
        this.newValue = newValue;
    }

    @Override
    public void undo() throws CannotUndoException {
        setTextIgnoringUndo(src, oldValue);
    }

    @Override
    public void redo() throws CannotRedoException {
        setTextIgnoringUndo(src, newValue);
    }

    @Override
    public boolean canUndo() {
        return true;
    }

    @Override
    public boolean canRedo() {
        return true;
    }

    public static void setTextIgnoringUndo(JTextField tf, String str) {
        PlainDocument doc = (PlainDocument) tf.getDocument();
        UndoableEditListener uel = doc.getUndoableEditListeners()[0];
        doc.removeUndoableEditListener(uel);
        tf.setText(str);
        doc.addUndoableEditListener(uel);
    }

}

另一个选项是覆盖文档#替换(…)


通过编程设置文本后,似乎是调用的好时机。@Andrew Thompson不,实际上我有一个带有一些文本操作的弹出菜单,如大写、反转字符串等。我希望这些操作可以在一次操作中撤消,否则用户一次单击就将字符串大写是不现实的,但是需要进行两次撤销才能去除资本。我并没有真正了解您的代码,但您的意思是在重载的撤销/重做方法中扩展UndoableEdit和make setText吗?
import java.awt.*;
import java.awt.event.*;
import java.util.Date;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.undo.*;
import javax.swing.event.*;

public class ReplaceUndoableEditDemo {
  private final UndoManager um = new UndoManager();
  private final JTextField tf = new JTextField(24);
  private final UndoManager undoManager = new UndoManager();
  private final JTextField field = new JTextField(24);
  private final Document doc = new PlainDocument() {
    @Override public void replace(
      int offset, int length, String text, AttributeSet attrs)
    throws BadLocationException {
      undoManager.undoableEditHappened(new UndoableEditEvent(
          this, new ReplaceUndoableEdit(offset, length, text)));
      replaceIgnoringUndo(offset, length, text, attrs);
    }
    private void replaceIgnoringUndo(
      int offset, int length, String text, AttributeSet attrs)
    throws BadLocationException {
      for(UndoableEditListener uel: getUndoableEditListeners()) {
        removeUndoableEditListener(uel);
      }
      super.replace(offset, length, text, attrs);
      for(UndoableEditListener uel: getUndoableEditListeners()) {
        addUndoableEditListener(uel);
      }
    }
    class ReplaceUndoableEdit extends AbstractUndoableEdit {
      private final String oldValue;
      private final String newValue;
      private int offset;
      public ReplaceUndoableEdit(int offset, int length, String newValue) {
        String txt;
        try {
          txt = getText(offset, length);
        } catch(BadLocationException e) {
          txt = null;
        }
        this.oldValue = txt;
        this.newValue = newValue;
        this.offset = offset;
      }
      @Override public void undo() throws CannotUndoException {
        try {
          replaceIgnoringUndo(offset, newValue.length(), oldValue, null);
        } catch(BadLocationException ex) {
          throw new CannotUndoException();
        }
      }
      @Override public void redo() throws CannotRedoException {
        try {
          replaceIgnoringUndo(offset, oldValue.length(), newValue, null);
        } catch(BadLocationException ex) {
          throw new CannotUndoException();
        }
      }
      @Override public boolean canUndo() {
        return true;
      }
      @Override public boolean canRedo() {
        return true;
      }
    }
  };
  public JComponent makeUI() {
    tf.getDocument().addUndoableEditListener(um);
    doc.addUndoableEditListener(undoManager);
    field.setDocument(doc);
    field.setText("aaaaaaaaa");
    tf.setText("default");
    JPanel p = new JPanel();
    p.add(tf);
    p.add(field);
    p.add(new JButton(new AbstractAction("undo") {
      @Override public void actionPerformed(ActionEvent e) {
        try {
          undoManager.undo();
          um.undo();
        } catch(Exception ex) {
          java.awt.Toolkit.getDefaultToolkit().beep();
        }
      }
    }));
    p.add(new JButton(new AbstractAction("redo") {
      @Override public void actionPerformed(ActionEvent e) {
        try {
          undoManager.redo();
          um.redo();
        } catch(Exception ex) {
          java.awt.Toolkit.getDefaultToolkit().beep();
        }
      }
    }));
    p.add(new JButton(new AbstractAction("setText") {
      @Override public void actionPerformed(ActionEvent e) {
        String str = new Date().toString();
        tf.setText(str);
        field.setText(str);
      }
    }));
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new ReplaceUndoableEditDemo().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}