Невозможно заставить свинг отменить / повторить работу системы для простой программы рисования.

1

Я следовал за шагами из многих статей, но система отмены не вела себя так, как ожидалось. во-первых, кнопка отмены возвращается правильно до первого редактирования, но не может выйти за пределы первого редактирования. также, когда я нажимаю кнопку "Отменить", а затем повторно редактирую его, круги возвращаются к последнему правлению. Это лучше, если вы выполните код и посмотрите сами.

Другой вопрос, в то время как я пытаюсь найти решение, я читал, что сохранение изображений в массиве является интенсивным с использованием памяти, верно ли это даже для этого простого класса лакирования и какова альтернатива? сохранение графического изображения?

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 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
Теги:
swing
undo

1 ответ

2

Вы не используете undoableIndex. На самом деле вам не следует удалять изображение из массива, а вместо этого перемещать указатель.

canUndo() должен возвращать true, если список не пуст, и указатель> 0

canRedo() должен возвращать true, если указатель! = size() в списке

  • 0
    Спасибо, вы имеете в виду, что я должен использовать undoableIndex в качестве указателя? Я изменил отмены и canUndo, но я все еще получаю тот же результат: public void undo() throws CannotUndoException { image = (BufferedImage)undoableImagesArray.get(undoableIndex-1); canvas.repaint(); } public boolean canUndo() { if(!undoableImagesArray.isEmpty() && undoableIndex>0) return true; return false;}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню