软件中Undo(撤回)和Redo(重做)的实现
在一般软件中,都会有Undo和Redo的功能,那么这个功能该怎么实现呢?在此介绍一种实现方法。(以lua语言为例)
1. 操作事件化。将用户的操作转换成一个事件数据,里面包括事件类型、操作目标、目标原始状态、操作后状态等。比如:
-- 移动某结点可转换为 local moveEvent = {event = "Move", target = "selectNode", orginPos = cc.p(0, 0), endPos = cc.p(100, 100)} -- 新建结点可转换为 local newEvent = {event = "Delete", name = "bgSprite"}
2. 事件处理与存储。新建一个类EventManager,用于存储所有的操作事件。在用户操作时并不直接执行对应的处理,而是将操作命令发给EventManager进行统一的处理。EventManager大致像这样:
-- eventList:存储用户操作的事件列表 -- statusIndex: 当前软件的执行事件位置 -- saveIndex: 当前软件的保存事件位置 EventManager = {eventList = {}, statusIndex = 0}
-- 新加事件 function EventManager:doEvent(cmd)-- 执行真正的操作变化 UIController:doEvent(cmd)-- 将当前操作位置之后的抛弃,statusIndex在发生Redo后将不再是列表长度for i=#self.eventList, (self.statusIndex + 1), -1 dotable.remove(self.eventList, i)end-- 加入事件队列table.insert(self.eventList, cmd)self.statusIndex = #self.eventList end
用户撤回(Undo)时,需要将上一个事件转换为撤回事件,如上文的moveEvent可转换为:
{event = "Move", target = "selectNode", orginPos = cc.p(100, 100), endPos = cc.p(0, 0)}
newEvent可转换为:
{event = "Delete", name = "bgSprite"}
具体undo方法大致如下:
-- 撤回操作 function EventManager:undo()if self.statusIndex > 0 then-- 获取撤回事件,依事件情况实现local undoCmd = self:getUndoCmd(self.eventList[self.statusIndex])self.statusIndex = self.statusIndex - 1-- 执行真正的操作变化 UIController:doEvent(undoCmd)end end
redo方法就比较简单了,只需将存储的事件再次执行即可:
-- 重做 function EventManager:redo()if self.statusIndex < #self.eventList thenself.statusIndex = self.statusIndex + 1local redoCmd = self.eventList[self.statusIndex]-- 执行真正的操作变化 UIController:doEvent(redoCmd)end end
以上我们就实现了操作的Undo和Redo功能。基于此我们可以引出另外一个功能:在软件中标注当前的修改状态,如图和。我们只需要在EventManager中添加一个变量saveIndex来标记当前的保存位置。当saveIndex==statusIndex时表示当前状态已保存,否则当前的修改未保存。需要在doEvent/undo/redo方法中刷新软件标题的显示状态。当用户保存时,则重置saveIndex的位置:
function EventManager:save()self.saveIndex = self.statusIndex-- 重置软件的标题fc.SetWindowTitle("fcediter") end
转载于:https://www.cnblogs.com/hghhe/p/9669107.html
软件中Undo(撤回)和Redo(重做)的实现相关推荐
- Oracle 中UNDO与REDO的差别具体解释
一 为了更清楚的看出2者差别,请看下表: UNDO ...
- oracle的redo和undo,Oracle的redo 和undo的區別
寫的次序: redo--> undo-->datafile insert一條記錄時, 表跟undo的信息都會放進 redo 中, 在commit 或之前, redo 的信息會放進硬盤上. ...
- MySQL日志(undo log 和 redo log 实现事务的原子性/持久性/一致性)
日志的重要性 日志绝对是数据库的核心. 持久化的日志记录了各种重要的信息. 数据的恢复需要依赖日志. 慢查询sql语句需要用到慢查询日志.以及错误日志中保存着mysqld数据库服务端在启动过程中 ...
- Oracle学习笔记:redo重做日志
redo重做日志对于oracle来说犹如 肝脏 那么重要,是oracle机能中的排毒恢复健康的重要部件!! 相关的基本概念: 1.scn 2.日志序列号 3.日志组 和 日志 成员,尤其是日志文件的尺 ...
- 中怎么撤回消息_微信消息撤回也能看到,这个开源神器牛x!语音、图片、文字都支持!...
1.前言 微信在2014年的时候,发布的v5.3.1 版本中推出了消息撤回功能,用户可以选择撤回 2 分钟内发送的最后一条信息. 现在很多即时通讯的软件都有撤回这个功能. 腾讯为了照顾手残党,在微信和 ...
- python里的demo是什么意思_软件中的“DEMO” 是什么意思?游戏中的“DEMO呢?
软件中的"DEMO" 是什么意思?游戏中的"DEMO呢? 2020-08-27 提示Initialization failure:0x0000000c错误无法上网?解决方 ...
- 电气设计软件中最常见的10个错误
设计早期的设备名称重复,组件之间交叉引用的断开链接以及耗时的组件生成,这些只是在低质量CAD软件中生成电气设计时发生的一些令人头疼的错误.这些花费大量时间修复的错误只是冰山一角.本文将深入探讨所有电气 ...
- 勒索文件恢复_我将如何从勒索软件中恢复
勒索文件恢复 There are very few things that genuinely worry me in cybersecurity. Recovering from ransomwar ...
- cad沿线插入块 lisp_CAD制图软件中如何快速绘制推拉窗平面简图
CAD建筑软件中为了方便绘图提供了强大的建筑门窗绘制功能.但是当电脑中没有CAD建筑软件的时候,怎么才能快速绘制出门窗或者简图呢?下面给大家分享一下CAD入门学习教程之在浩辰CAD中绘制推拉窗平面简图 ...
最新文章
- spring集成xmemcached
- icem密度盒怎么设置_icem一些总结精编版
- python一些小操作
- 解决android studio引用远程仓库下载慢(JCenter下载慢)
- 加装的硬盘进入后点不了文件夹_在外接移动硬盘上制作win to go教程
- js中数字直接点方法会报错,如1.toString()
- python时间格式化
- sql server 替换字符串中的某些字符
- js去掉前后空格的函数_Node.js十年,你大爷还是你大爷
- 人脑词典、亡者归来……来看库兹韦尔对于未来的四个疯狂预测
- 计算机毕业设计项目推荐 - 毕设开题选题
- refind引导的win10+ubuntu18.04开机启动
- 使用线程持续产生随机数
- 雍正王朝里康熙临终予四爷言
- Android使用第三方字体
- Latex完成入侵检测系统综述论文
- 2021-2022-1 ACM集训队每周程序设计竞赛(5) - 问题 C: 剪切 - 题解
- 各国际会议的影响因子
- Effective C++知识点
- 数学建模从入门到放弃
热门文章
- 电脑音频服务未运行怎么解决_【电脑技能】女生专属,学会这几招也可以修好你的电脑...
- 永恒python怎么用_毫无基础的人如何入门 Python ?Python入门教程拿走不谢啦!
- 仓库货位卡标识牌_仓库应如何规划?
- 火影忍者服务器维护时间,火影手游12月12日更新:仙鸣增加破霸体,小自来也变蛙时间减半!...
- python包管理工具ports_如何从自制程序,分发,macports,pip卸载所有软件包?
- [USACO13FEB]Tractor【二分 + BFS】
- docker︱在nvidia-docker中使用tensorflow-gpu/jupyter
- REVerb三元抽取工具
- python爬取公众号,用最简单的方式爬虫
- IDEACould not autowire. No beans of 'xxxMapper' type found.