【问题标题】:How to implement Undo and Redo feature in as3as3中如何实现Undo和Redo功能
【发布时间】:2011-10-06 09:02:09
【问题描述】:

我将创建一个应用程序,其中我必须实现 撤消和重做 功能。 在应用程序中,舞台上会有多个对象,用户可以自定义 物体的位置。但是当用户单击撤消对象时,该对象将返回其默认值 位置,单击重做对象后将移动到新位置。

所以我的问题是如何在我的应用程序中应用这些功能? 是否有任何库或任何第三方类?

有人可以帮我吗?

提前致谢。

【问题讨论】:

  • 如何实现多个对象的撤消和重做?我们可以在 as3 中有任何第三方类吗?

标签: flash actionscript-3 apache-flex flash-builder flash-cs5


【解决方案1】:

看看command pattern。它非常适合撤销/重做类型的问题。

【讨论】:

  • 命令模式本身是不够的。通常与Memento-pattern 关联使用。
【解决方案2】:

如果您只想要两种不同的状态(默认和“已更改”),实现起来应该很简单。将每个对象的新值和更新值存储在数组中,并在按下“撤消”或“重做”时从相关数组中设置位置。

如果您需要更复杂的东西,您可以将您所做的一切存储为可撤消的“操作”。例如,有一个类(例如“Action”)有几个子类(“Move”、“ChangeColor”等)。它们包含它们执行的更改(我们应该移动多少像素)以及执行操作(移动对象 X 像素)和撤消操作(移动对象 -X 像素)的方法。

【讨论】:

    【解决方案3】:

    我能想到的最简单的方法是创建一个动作对象,其中有旧状态和新状态以及发生变化的对象。

    每次触发会获得撤消功能的操作时,在操作对象中填写此数据

    当您点击撤消时,恢复到对象的之前状态并将操作推入重做堆栈。

    这应该能够处理最常见的更改。删除/取消删除之类的东西需要一些额外的调整。我会在删除时放入所有属性,并在处理撤消时使用创建函数。

    我建议对前后状态的参数和值组合使用字符串,这样您就可以在不更改撤消/重做功能的情况下处理其他功能。

    这更像是一种快速而肮脏的方式,您也可以使用其他人提到的设计模式和适当的 OOP 方式来处理这个问题。

    【讨论】:

    • 你能给我一些代码块让我继续吗?
    【解决方案4】:
     package com
     {
        import flashx.undo.IOperation;
    
        public class UndoOperation implements IOperation
        {
    
        private var _previousX:Number = 0;
        private var _previousY:Number = 0;
        private var _previousObj:Object = new Object();
        private var _currentX:Number = 0;
        private var _currentY:Number = 0;
        private var _currentObj:Object = new Object();
        private var _shape:Object = new Object();
    
    
        public function TransformOperation(currentObj:Object,previousObj:Object,previousX:Number, previousY:Number, currentX:Number, currentY:Number)
        {
            _previousX = previousX;
            _previousY = previousY;
            _previousObj = previousObj;
    
            _currentX = currentX;
            _currentY = currentY;
            _currentObj = currentObj;
            _shape = _currentObj;
    
            trace('Transform _previousX:  '+  _previousX  +' _previousY:  ' +_previousY+' _currentObj '+_currentObj+' _shape '+_shape);
            trace( 'trans _currentX    '+ _currentX +'  '+'_currentY     '+ _currentY );
    
        }
    
        public function performUndo():void
        {
            _shape = _currentObj;
            //trace('_shape.x '+_shape.x+" _shape.y "+_shape.y);
            _shape.x = _previousX;
            _shape.y = _previousY;
            //trace(_previousX +'  '+ _previousY +'  '+ _previousWidth +'  '+ _previousHeight +'  '+  _previousScaleX +'  '+  _previousScaleY +'  '+ _previousRotation);
            //trace('_shape.x '+_shape.x+" _shape.y "+_shape.y);
            //trace('_currentX    '+ _currentX +'  '+'_currentY     '+ _currentY);
        }
    
        public function performRedo():void
        {
            _shape.x = _currentX;
            _shape.y = _currentY;
            trace(_currentX+'  '+ _currentY);
        }
      }
    }
    

    这是我在舞台上撤消和重做多个对象的自定义类。有不同的模式可用于撤消和重做操作,但对我来说这是撤消和重做的简单方法。我已经在我的项目中完美且成功地实现了这一点。

    要使用这个类,只需要导入这个类

                     import flashx.undo.UndoManager;
    

    然后

                public static var _undo:UndoManager=new UndoManager();
                public static var _redo:UndoManager=new UndoManager();     
                public static var PrevX:Number=0;
                public static var PrevY:Number=0;
                var operation:TransformOperation = new TransformOperation(this,this,PrevX,PrevY,this.x,this.y);
               _undo.pushUndo(operation);
    

    之后为撤销和重做创建点击事件:

        public static function Undo(e:MouseEvent):void
        {
            _redo.pushRedo(_undo.peekUndo());
            _undo.undo();
            if(_undo.peekUndo()==null)
            {
                PlayerPosition.getClass.getChildByName("toolbar_mc").getChildByName("undo_mc").removeEventListener(MouseEvent.CLICK,Undo);
            }
            PlayerPosition.getClass.getChildByName("toolbar_mc").getChildByName("redo_mc").addEventListener(MouseEvent.CLICK,Redo);
        }
    
        public static function Redo(e:MouseEvent):void
        {
            _undo.pushUndo(_redo.peekRedo());
            _redo.redo();
            if(_redo.peekRedo()==null)
            {                          PlayerPosition.getClass.getChildByName("toolbar_mc").getChildByName("redo_mc").removeEventListener(MouseEvent.CLICK,Redo);
            }
            PlayerPosition.getClass.getChildByName("toolbar_mc").getChildByName("undo_mc").addEventListener(MouseEvent.CLICK,Undo);
        }
    

    对我来说这很好用...希望这对其他人也有帮助...:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-07
      • 2013-02-25
      • 2010-10-16
      • 2012-07-21
      • 1970-01-01
      • 1970-01-01
      • 2011-09-26
      • 2010-12-22
      相关资源
      最近更新 更多