JTextArea setText()&的UndoManager [英] JTextArea setText() & UndoManager

查看:179
本文介绍了JTextArea setText()&的UndoManager的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 UndoManager 来捕获我的 JTextArea 中的更改。

I'm using an UndoManager to capture changes in my JTextArea.

方法 setText()然而删除所有内容然后粘贴文本。当我撤消时,我首先看到一个空白区域,然后它会显示之前的文本。

The method setText() however deletes everything and then pastes the text. When I undo I firstly see an empty area and then it would show which text it had before.

如何重现:


  1. 运行以下代码

  2. 点击 setText()按钮

  3. CTRL + Z 撤消(你会看到一个空的textarea!)

  4. CTRL + Z 撤消(你会看到实际的前一个文字)

  1. Run the following code
  2. Click the setText() button
  3. Press CTRL+Z to undo (you'll see an empty textarea!)
  4. Press CTRL+Z to undo (you'll see the actual previous text)

我想跳过3)。

import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.Document;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

import java.awt.event.ActionEvent;
import javax.swing.JButton;
import java.awt.event.ActionListener;

@SuppressWarnings("serial")
public class JTextComponentSetTextUndoEvent extends JFrame
{
    JTextArea area = new JTextArea();

    public JTextComponentSetTextUndoEvent()
    {
        setSize(300, 300);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        getContentPane().setLayout(null);

        area.setText("Test");
        area.setBounds(0, 96, 146, 165);
        getContentPane().add(area);

        JButton btnSettext = new JButton("setText()");
        btnSettext.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent arg0)
            {
                area.setText("stackoverflow.com");
            }
        });
        btnSettext.setBounds(0, 28, 200, 50);
        getContentPane().add(btnSettext);

        final UndoManager undoManager = new UndoManager();
        Document doc = area.getDocument();

        doc.addUndoableEditListener(new UndoableEditListener()
        {
            public void undoableEditHappened(UndoableEditEvent evt)
            {
                undoManager.addEdit(evt.getEdit());
            }
        });

        area.getActionMap().put("Undo", new AbstractAction("Undo")
        {
            public void actionPerformed(ActionEvent evt)
            {
                try
                {
                    if (undoManager.canUndo())
                    {
                        undoManager.undo();
                    }
                } catch (CannotUndoException e)
                {
                }
            }
        });

        area.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo");

        area.getActionMap().put("Redo", new AbstractAction("Redo")
        {
            public void actionPerformed(ActionEvent evt)
            {
                try
                {
                    if (undoManager.canRedo())
                    {
                        undoManager.redo();
                    }
                } catch (CannotRedoException e)
                {
                }
            }
        });

        area.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo");
    }

    public static void main(String[] args)
    {
        new JTextComponentSetTextUndoEvent().setVisible(true);
    }
}


推荐答案

你可以尝试这样的事情:

You can try something like this:

//Works fine for me on Windows 7 x64 using JDK 1.7.0_60:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;

public final class UndoManagerTest {
  private final JTextField textField0 = new JTextField("default");
  private final JTextField textField1 = new JTextField();
  private final UndoManager undoManager0 = new UndoManager();
  private final UndoManager undoManager1 = new UndoManager();

  public JComponent makeUI() {
    textField1.setDocument(new CustomUndoPlainDocument());
    textField1.setText("aaaaaaaaaaaaaaaaaaaaa");

    textField0.getDocument().addUndoableEditListener(undoManager0);
    textField1.getDocument().addUndoableEditListener(undoManager1);

    JPanel p = new JPanel();
    p.add(new JButton(new AbstractAction("undo") {
      @Override public void actionPerformed(ActionEvent e) {
        if (undoManager0.canUndo()) {
          undoManager0.undo();
        }
        if (undoManager1.canUndo()) {
          undoManager1.undo();
        }
      }
    }));
    p.add(new JButton(new AbstractAction("redo") {
      @Override public void actionPerformed(ActionEvent e) {
        if (undoManager0.canRedo()) {
          undoManager0.redo();
        }
        if (undoManager1.canRedo()) {
          undoManager1.redo();
        }
      }
    }));
    p.add(new JButton(new AbstractAction("setText(new Date())") {
      @Override public void actionPerformed(ActionEvent e) {
        String str = new Date().toString();
        textField0.setText(str);
        textField1.setText(str);
      }
    }));

    Box box = Box.createVerticalBox();
    box.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    box.add(makePanel("Default", textField0));
    box.add(Box.createVerticalStrut(5));
    box.add(makePanel("replace ignoring undo", textField1));

    JPanel pp = new JPanel(new BorderLayout());
    pp.add(box, BorderLayout.NORTH);
    pp.add(p, BorderLayout.SOUTH);
    return pp;
  }
  private static JPanel makePanel(String title, JComponent c) {
    JPanel p = new JPanel(new BorderLayout());
    p.setBorder(BorderFactory.createTitledBorder(title));
    p.add(c);
    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 UndoManagerTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class CustomUndoPlainDocument extends PlainDocument {
  private CompoundEdit compoundEdit;
  @Override protected void fireUndoableEditUpdate(UndoableEditEvent e) {
    if (compoundEdit == null) {
      super.fireUndoableEditUpdate(e);
    } else {
      compoundEdit.addEdit(e.getEdit());
    }
  }
  @Override public void replace(
      int offset, int length,
      String text, AttributeSet attrs) throws BadLocationException {
    if (length == 0) {
      System.out.println("insert");
      super.replace(offset, length, text, attrs);
    } else {
      System.out.println("replace");
      compoundEdit = new CompoundEdit();
      super.fireUndoableEditUpdate(new UndoableEditEvent(this, compoundEdit));
      super.replace(offset, length, text, attrs);
      compoundEdit.end();
      compoundEdit = null;
    }
  }
}

这篇关于JTextArea setText()&的UndoManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆