实现文本框输入内容的单条记录撤销,重做,通过按钮实现

以及通过JList的多条撤销、重做操作(类似PS)

昨天还在为自己写不出代码怎么办而伤心,没想到今天上午就实现了,并且还完善了功能:

可以在撤销一些操作后,继续编辑文本框,同时给Jlist添加渲染。

代码如下:

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package UndoText; import com.sun.media.sound.ModelAbstractChannelMixer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit; /**
*
* @author Administrator
*/
//实现文本框的撤销、重做
public class UndoTextFrame extends JFrame { JPanel undoListJPanel = new JPanel();
JList undoList = new JList();
JScrollPane undoScrollPane = new JScrollPane(undoList);
DefaultListModel listModel = new DefaultListModel<>();
UndoManager um = new UndoManager();
int[] undoIndexs;
int indexF, indexS; public UndoTextFrame() {
setTitle("sample");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setSize(640, 480);
setLocationRelativeTo(this);
getContentPane().add(new textPanel(), BorderLayout.CENTER);
getContentPane().add(undoListPanel(), BorderLayout.WEST); } public JPanel undoListPanel() {
undoListJPanel.setLayout(new BorderLayout());
undoList.setModel(listModel);
undoList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
undoList.setFixedCellWidth(100); // undoIndexs = new int[indexS]; undoScrollPane.setPreferredSize(new Dimension(100, 400));
undoScrollPane.setBorder(BorderFactory.createTitledBorder("Undo"));
undoScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
undoScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
undoListJPanel.add(undoScrollPane, BorderLayout.NORTH);
UndoListManager();
return undoListJPanel; } public void UndoListManager() { undoList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent lse) {
System.out.println("F:" + indexF);
System.out.println("S:" + indexS);
if (undoList.getValueIsAdjusting()) {
indexS = undoList.getSelectedIndex();
} else {
indexF = undoList.getSelectedIndex();
}
undoIndexs = new int[undoList.getLastVisibleIndex()];
for (int j = 0; j < indexS; j++) {
undoIndexs[j] = undoList.getSelectedIndex();
}
MyRenderer renderer = new MyRenderer(undoIndexs, Color.PINK);
undoList.setCellRenderer(renderer); if (indexF < indexS) {
for (int i = indexF; i < indexS; i++) {
if (um.canRedo()) {
um.redo();
}
}
} else if (indexF > indexS) {
for (int i = indexF; i > indexS; i--) {
if (um.canUndo()) {
um.undo();
} }
}
}
});
} //quesion:textPane setLineCrap
class textPanel extends JPanel { private JTextPane textPane = new JTextPane();
private JScrollPane scrollTextPane1 = new JScrollPane(textPane);
// private JLabel textTitle = new JLabel("TextPane");
JPanel header = new JPanel();
JToolBar toolBar = new JToolBar();
JButton undoButton = new JButton("undo");
JButton redoButton = new JButton("redo"); public textPanel() {
setLayout(new BorderLayout());
textPane.setEditable(true);
textPane.setToolTipText("textPane");
scrollTextPane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollTextPane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); toolBar.add(redoButton);
toolBar.add(undoButton);
toolBar.setFloatable(false);
header.setLayout(new BorderLayout());
header.add(toolBar, BorderLayout.CENTER);
add(header, BorderLayout.NORTH);
add(scrollTextPane1, BorderLayout.CENTER);
initAction();
} public void initAction() { textPane.getDocument().addUndoableEditListener(new UndoableEditListener() {
@Override
public void undoableEditHappened(UndoableEditEvent uee) { um.addEdit((UndoableEdit) uee.getEdit());
listModel.addElement(textPane.getText().toString().charAt(textPane.getText().length() - 1)); MyRenderer renderer = new MyRenderer(textPane.getText().length() - 1, Color.yellow);
undoList.setCellRenderer(renderer); textPane.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent ke) {
for (int k = indexS + 1; k < undoList.getModel().getSize(); k++) {
listModel.removeElementAt(k);
}
}
}); indexF = listModel.getSize() - 1;
indexS = listModel.getSize() - 1;
}
}); undoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (um.canUndo()) {
um.undo();
}
}
});
redoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (um.canRedo()) {
um.redo();
}
}
});
}
} //Jlist render
class MyRenderer extends DefaultListCellRenderer { private Font font1;
private Font font2;
private Color rowcolor;
private int row;
private int[] rows;
private DefaultListModel model; public MyRenderer() {
this.font1 = getFont();
this.font2 = font1.deriveFont((float) (font1.getSize() + 10));
} public MyRenderer(int row, Color color) {
this.rowcolor = color;
this.row = row;
} public MyRenderer(int[] rows, Color color) {
this.rowcolor = color;
this.rows = rows;
} public MyRenderer(Color rowcolor, DefaultListModel model) {
this.rowcolor = rowcolor;
this.model = model;
} public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (rows == null) {
if (index == row) {
setBackground(this.rowcolor);
//setFont(getFont().deriveFont((float) (getFont().getSize() + 2)));
}
} else {
for (int i = 0; i < rows.length; i++) {
if (index <= rows[i]) {
setBackground(this.rowcolor);
}
}
}
return this;
}
} public static void main(String[] args) {
new UndoTextFrame().setVisible(true); }
}

JTextPane 的 undo 、 redo的更多相关文章

  1. MySQL,MariaDB:Undo | Redo [转]

    本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...

  2. iOS: 为画板App增加 Undo/Redo(撤销/重做)操作

    这个随笔的内容以上一个随笔为基础,(在iOS中实现一个简单的画板),上一个随笔实现了一个简单的画板:   今天我们要为这个画板增加Undo/Redo操作,当画错了一笔,可以撤销它,或者撤销之后后悔了, ...

  3. [转]MySQL日志——Undo | Redo

    本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...

  4. 从Undo,Redo谈命令模式

    一般的应用软件中,通常会提供Redo和Undo的操作,比如Paint.NET中的动作面板,Word中的撤销重做,一般我们按Ctrl-Z即可回退到上次操作. 要实现上面的这一功能,最直观的想法就是,我们 ...

  5. Undo/Redo for Qt Tree Model

    Undo/Redo for Qt Tree Model eryar@163.com Abstract. Qt contains a set of item view classes that use ...

  6. 【转载】MySQL 日志 undo | redo

    本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...

  7. MySQL InnoDB存储引擎undo redo解析

    本文介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 为了实现事务原子,在MySQL数据库InnoDB存储引擎,还使用Undo Log(简称:MVCC ...

  8. MySQL日志Undo&Redo

    00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomi ...

  9. MySql Undo Redo

    Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomicity) ...

  10. 转:C#中Undo/Redo的一个简易实现

    一个比较常见的改进用户体验的方案是用Redo/Undo来取代确认对话框,由于这个功能比较常用,本文简单的给了一个在C#中通过Command模式实现Redo/Undo方案的例子,以供后续查询. clas ...

随机推荐

  1. 前端MVVM学习之KnockOut(二)

    现在开始学习Knockout并且做个简单的例子. Knockout是建立在以下三个核心功能之上的: 1.Observables and dependency tracking(属性监控与依赖跟踪) 2 ...

  2. Ext4报错Uncaught Ext.Loader is not enabled

    提示: Uncaught Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. Missing requ ...

  3. Javascript 文件的同步加载与异步加载

    HTML 4.01 的script属性 charset: 可选.指定src引入代码的字符集,大多数浏览器忽略该值.defer: boolean, 可选.延迟脚本执行,相当于将script标签放入页面b ...

  4. Webix快速跨浏览器的JavaScript UI组件

    网址:http://webix.com/ 寥寥几行代码就将页面渲染出来了,确实值得一试!

  5. 搜索和搜索形式(SEARCHING and its forms)

    什么是搜索? 在计算机科学中,搜索就是在一个事物的集合中找到具有特定特征的一项的过程.这些集合中的元素可能是排好序的数据库中的记录,简单数组中的数据,文件中的文本,树中的节点,几何图形中的点和边或者是 ...

  6. 360WIFI下使用Fiddler抓取手机APP流量

    过程其实很简单,仅仅做个记录.过程适用Android和ios手机 fidder的原理如下: 下面开始步骤: 1.在fidder中设置代理:Tools--->Fidder Options,设置端口 ...

  7. Velocity.js发布:更快的动画切换速度

    Velocity.js是一款动画切换的jQuery插件,它重新实现了jQuery的$.animate()方法从而加快动画切换的速度.Velocity.js只有7k的大小,它不仅包含了$.animate ...

  8. kafka中处理超大消息的一些考虑

    Kafka设计的初衷是迅速处理短小的消息,一般10K大小的消息吞吐性能最好(可参见LinkedIn的kafka性能测试).但有时候,我们需要处理更大的消息,比如XML文档或JSON内容,一个消息差不多 ...

  9. PHP中的的一个挺好用的函数 array_chunk

  10. Git使用过程

    Git-------目前世界上最先进的分布式版本控制系统(没有之一) 什么是版本控制系统? 说简单点,就是一个文件,对其增加.删除.修改都可以被记录下来,不仅自己可以修改,其他人也可以进行修改 每次对 ...