JTextPane 的 undo 、 redo
实现文本框输入内容的单条记录撤销,重做,通过按钮实现
以及通过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的更多相关文章
- MySQL,MariaDB:Undo | Redo [转]
本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...
- iOS: 为画板App增加 Undo/Redo(撤销/重做)操作
这个随笔的内容以上一个随笔为基础,(在iOS中实现一个简单的画板),上一个随笔实现了一个简单的画板: 今天我们要为这个画板增加Undo/Redo操作,当画错了一笔,可以撤销它,或者撤销之后后悔了, ...
- [转]MySQL日志——Undo | Redo
本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...
- 从Undo,Redo谈命令模式
一般的应用软件中,通常会提供Redo和Undo的操作,比如Paint.NET中的动作面板,Word中的撤销重做,一般我们按Ctrl-Z即可回退到上次操作. 要实现上面的这一功能,最直观的想法就是,我们 ...
- 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 ...
- 【转载】MySQL 日志 undo | redo
本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...
- MySQL InnoDB存储引擎undo redo解析
本文介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 为了实现事务原子,在MySQL数据库InnoDB存储引擎,还使用Undo Log(简称:MVCC ...
- MySQL日志Undo&Redo
00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomi ...
- MySql Undo Redo
Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomicity) ...
- 转:C#中Undo/Redo的一个简易实现
一个比较常见的改进用户体验的方案是用Redo/Undo来取代确认对话框,由于这个功能比较常用,本文简单的给了一个在C#中通过Command模式实现Redo/Undo方案的例子,以供后续查询. clas ...
随机推荐
- Bing必应(Yahoo雅虎)搜索引擎登录网站 - Blog透视镜
Bing必应是微软的搜索引擎,原本是置放在MSN网站上的,微软重新开发并改为新的名子,只要连到官网,登录网站后,过了不久,搜索引擎就会用爬虫,来检索你的网站,等过了一阵子之后,自然就可以找到你的文章. ...
- 全 Javascript 的 Web 开发架构:MEAN
http://developer.51cto.com/art/201404/434759.htm 全 Javascript 的 Web 开发架构:MEAN 引言 最近在Angular社区的原型开发者间 ...
- 线程初步了解 - <第一篇>
操作系统通过线程对程序的执行进行管理,当操作系统运行一个程序的时候,首先,操作系统将为这个准备运行的程序分配一个进程,以管理这个程序所需要的各种资源.在这些资源之中,会包含一个称为主线程的线程数据结构 ...
- mCustomScrollbar的使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- Linux系统编程(7)—— 进程之进程概述
我们知道,每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体.现在我们全面了解一下其中都有哪些信息. 进程id.系统中每个进程有 ...
- C语言中指针的指针是如何工作的?
我们有时看到这样地饿代码: int *ptr = &x; 这里,ptr是一个指向x在内存中的地址的指针. 假设有另外一条语句是这样地的: int **ptr2 = &ptr; 我们 ...
- LeeCode-Remove Duplicates from Sorted List
Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...
- wireshark----教你如何抓包
wireshark----教你如何抓包 wireshark是一款强大的抓包工具,走过路过一定不要错过就是了,当你学习TCP/IP协议的时候,学习使用wireshark 抓包正是理论联系实际最好的方法, ...
- iOS 实时监听app的网络连接状态
实际iOS开发中,在网络通信中我们大部分使用第三方(只谈短链),譬如 AFNetworking.ASIHttpRequest(这个停更了,想必现在没多少人用),swift的 Alamofire 等. ...
- Pasha and String(思维,技巧)
Pasha and String Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u S ...