无法使摆动撤销/重做系统适用于简单的绘图程序。

时间:2014-03-14 10:33:49

标签: java swing undo

我按照许多文章中的步骤操作,但撤消系统的行为不符合预期。首先,撤消按钮正确返回到第一次编辑,但不能超出第一次编辑。另外,当我点击撤消然后重新编辑它时,回到最后一次编辑。如果你执行代码并看到自己,那就更好了。

另一个问题,虽然我正在试图找出一个解决方案,我读到在数组中保存图像是内存密集型的,即使对于这个简单的绘图类也是如此,还有什么选择?保存图像的图形?

import java.awt.*;import java.awt.image.BufferedImage;import java.awt.event.*;import java.util.ArrayList;import javax.swing.*;import javax.swing.event.*;import javax.swing.undo.*;
public class Painter extends JFrame{    
//attributes//
Painter.Canvas canvas;
JPanel controlPanel;
JButton undoButton;
JButton redoButton;
PainterHandler handler;
Container container;
//undo system elements//
UndoManager undoManager;         // history list
UndoableEditSupport undoSupport; // event support

//constructor//
public Painter()
{
    super("Painter-test");
    controlPanel = new JPanel();
    undoButton = new JButton("undo");
    redoButton = new JButton("redo");
    handler = new Painter.PainterHandler();
    container = getContentPane();
    canvas = new Painter.Canvas();

    this.organizer();
}// end constructor

public void organizer()
{
    controlPanel.setLayout(null);
    controlPanel.setPreferredSize(new Dimension(120,350));
    controlPanel.setBackground(null);

    //add undo listeners to undo/redo buttons.
    undoButton.addActionListener( new AbstractAction()
                {
                    public void actionPerformed( ActionEvent evt ) 
                    { undoManager.undo(); refreshCanvas(); refreshUndoRedo();}
                });
    redoButton.addActionListener(new AbstractAction() 
                {
                    public void actionPerformed(ActionEvent evt ) 
                    { undoManager.redo(); refreshCanvas(); refreshUndoRedo(); }
                });

    // initilize the undo/redo system.
    undoManager= new UndoManager();//history list
    // event support, instance.
    undoSupport = new UndoableEditSupport();
     //add undoable edit listener to the support instance.
    undoSupport.addUndoableEditListener(new UndoableEditListener() 
                {
                    public void undoableEditHappened (UndoableEditEvent event) 
                    { 
                        UndoableEdit edit = event.getEdit();
                        undoManager.addEdit( edit ); 
                        refreshUndoRedo();
                    }
                });
    refreshUndoRedo();

    canvas.setPreferredSize(new Dimension(600,400));
    //place buttons on panel.
    undoButton.setBounds(10, 160, 80, 20);
    redoButton.setBounds(10, 181, 80, 20);

    //add components to panel.
    controlPanel.add(undoButton);
    controlPanel.add(redoButton);

    //add panels to window.
    container.add(canvas,BorderLayout.WEST);
    container.add(controlPanel, BorderLayout.EAST);
}//end organizerTab3()

public void refreshCanvas() { canvas.repaint(); }

//refresh undo, redo buttons.
public void refreshUndoRedo() 
{
    // refresh undo
    undoButton.setEnabled( undoManager.canUndo() );
    // refresh redo
    redoButton.setEnabled( undoManager.canRedo() );
}


//INNER CLASSES
ArrayList<BufferedImage> imagesArray = new ArrayList<BufferedImage>();
BufferedImage imageCopy;
Graphics graphics;
BufferedImage  image;
int index;
private class Canvas extends JPanel 
{
    public Canvas() 
    {
        //Panel properties
        setSize(600,400);
        setBackground(new Color(84,84,118));

        image = new BufferedImage(getWidth(), getHeight(),BufferedImage.TYPE_INT_ARGB);
        //add Listeners.
        addMouseMotionListener(handler);
        addMouseListener(handler);
    }//end constructor

    @Override
    public void paintComponent(Graphics g) 
    {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, null);
    }
}//end inner class PaintPanel


private class PainterHandler extends MouseAdapter
{
    @Override
    public void mouseDragged(MouseEvent event)
    {
        if(event.getComponent().equals(canvas))
        {
            if (image != null)
            {
            // Paint into the image
            graphics = image.getGraphics();
            graphics.setColor(new Color(249,30,138));
            graphics.fillOval(event.getX(), event.getY(), 20, 20);
            imageCopy = new BufferedImage(canvas.getWidth(),canvas.getHeight(),BufferedImage.TYPE_INT_ARGB);
            imageCopy.getGraphics().drawImage(image, 0, 0, null);
            canvas.repaint();
            }
        }
    }//end mouseDragged(MouseEvent event)

    @Override
    public void mouseReleased(MouseEvent event)
    {
        if(event.getComponent().equals(canvas))
        {
            //UNDO SYSTEM START//
            //add image to the array.
            imagesArray.add(imageCopy);
            // get image's index.
            index = imagesArray.indexOf(imageCopy);
            //create AddEdit instance of type UndoableEdit. 
            UndoableEdit edit = new Painter.AddEdit(imagesArray, imageCopy,index);
            // notify the listeners
            undoSupport.postEdit( edit );
            //UNDO SYSTEM END//
        }
    }
}//end MouseHandler class

private class AddEdit extends AbstractUndoableEdit
{
    private ArrayList<BufferedImage> undoableImagesArray;
    private BufferedImage undoableImage;
    int undoableIndex;
    public AddEdit(ArrayList<BufferedImage> v, BufferedImage img, int i) 
    {
        undoableImagesArray = v;
        undoableImage = img;
        undoableIndex = i;
    }
    public void undo() throws CannotUndoException 
    {
      undoableImagesArray.remove(undoableImage);
      if(!undoableImagesArray.isEmpty()) 
          image = (BufferedImage)undoableImagesArray.get(undoableImagesArray.size()-1);
      canvas.repaint();
    }

    public void redo() throws CannotRedoException 
    {
        undoableImagesArray.add(undoableImage);
        image = (BufferedImage)undoableImagesArray.get(undoableImagesArray.size()-1); 
        canvas.repaint();
    }

    public boolean canUndo() { return true; }
    public boolean canRedo() { return true; }
}//end class AddEdit

public static void main(String[] s)
{
    Painter p = new Painter();
    p.setSize(800, 500);
    p.setVisible(true);
    p.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} 
}//END CLASS Painter

1 个答案:

答案 0 :(得分:2)

您不使用undoableIndex。实际上,您不应该从数组中删除图像,而是移动指针。

如果列表不为空且指针&gt; 0

,则

canUndo()应返回true 如果列表的指针!= size()

canRedo()应该返回true