当前位置: 首页 > 面试题库 >

JTextArea setText()和UndoManager

葛季萌
2023-03-14
问题内容

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

setText()但是,该方法将删除所有内容,然后粘贴文本。撤消操作时,我首先会看到一个空白区域,然后它会显示以前的文本。

繁殖方法:

  1. 运行以下代码
  2. 点击setText()按钮
  3. CTRL+Z撤消(您将看到一个空的文本区域!)
  4. CTRL+Z撤消(您将看到实际的先前文本)

我想跳过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);
    }
}

问题答案:

您可以尝试如下操作:

//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;
    }
  }
}


 类似资料:
  • 问题内容: 关于它们有很多传说。我想知道真相。以下两个示例之间有什么区别? 问题答案: 不确定从何处获得传说,但: 提交按钮 与: IE6将在标记之间提交此按钮的所有文本,其他浏览器将仅提交值。使用可使您在按钮的设计上享有更大的布局自由度。从各种意图和目的看,它乍一看似乎很棒,但是各种浏览器怪癖使它有时很难使用。 在您的示例中,IE6将发送到服务器,而其他大多数浏览器将不发送任何内容。要使其跨浏览

  • 什么区别以及如何正确重写代码?

  • 我试图理解为什么下面两个代码块会产生不同的结果。 代码块1按预期工作,并返回从数据库中查找的提供程序的数组。另一方面,代码块2返回函数数组。在理解promissione.all()和async/await时,我觉得缺少了一些简单的东西。 代码块的差异如下: > 块1:创建许诺函数数组,然后使用map运算符将其包装在异步函数中。 块2:许诺函数的数组被创建为异步函数。因此,不调用map运算符。 如果

  • 问题内容: 我才刚刚开始研究SQL。 我有一个SQL Server 2008r2数据库,它将返回两个字段DocDate和InvValue。我需要将InvValues汇总为今天的MTD和YTD,所以看起来像 我已经做了大量的Google搜寻,并且可以使用SUM&DATEPART进行一项或多项,但是我坚持尝试两者兼而有之。 有人可以给我一些伪代码,以帮助我进一步谷歌。 谢谢@戈登·利诺夫(Gordon

  • 这个示例代码来自一本Java书籍,从墙上的99瓶啤酒到没有啤酒打印出这首歌。问题是,当墙上是1瓶啤酒时,它仍然写着瓶子。我试图通过在末尾添加部分来解决这个问题。但是,它仍然显示1瓶啤酒在墙上,我瓶啤酒在墙上。 我不知道该改变什么来解决这个问题。是否创建另一个while部分? 如果你能给他们一个提示,这样我就可以自己解决它,那也很酷!因为我知道我的实际歌曲输出是在第一个if部分,但我不知道我应该在哪

  • 原文地址:https://cesiumjs.org/tutorials/cesium-and-webpack/ Cesium 和 Webpack Webpack是非常强大非常流行的JavaScript 模块打包工具。它可以让开发人员以一种简单直观的 require 方式去加载各种页面需要的文件,极大的方便了开源人员对代码和资源文件进行结构化设计。当编译的时候,它会跟踪代码依赖性,把所有的模型打包到