gpt4 book ai didi

java - 绘画程序的撤消方法

转载 作者:行者123 更新时间:2023-12-01 18:32:19 25 4
gpt4 key购买 nike

我正在尝试在我的一个程序中创建一个小绘图板。这是类(class):

class DrawPad extends JComponent {

Image image;
Graphics2D graphics;
int currentX, currentY, oldX, oldY;

public DrawPad() {
setDoubleBuffered(false);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
oldX = e.getX();
oldY = e.getY();
}
});

addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
currentX = e.getX();
currentY = e.getY();
if (graphics != null) {
graphics.drawLine(oldX, oldY, currentX, currentY);
}
repaint();
oldX = currentX;
oldY = currentY;
}
});
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null) {
image = createImage(getSize().width, getSize().height);
graphics = (Graphics2D) image.getGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, null);
}

public void clear() {
graphics.setPaint(Color.white);
graphics.fillRect(0, 0, getSize().width, getSize().height);
graphics.setPaint(Color.black);
repaint();
}

public void undo() {
// restore previous graphics here
}

public void red() {
graphics.setPaint(Color.red);
repaint();
}

public void black() {
graphics.setPaint(Color.black);
repaint();
}

public void magenta() {
graphics.setPaint(Color.magenta);
repaint();
}

public void blue() {
graphics.setPaint(Color.blue);
repaint();
}

public void green() {
graphics.setPaint(Color.green);
repaint();
}

}

我将它添加到 JPanel 中。绘图本身效果很好。现在我想实现一个撤消方法。我认为我可以将当​​前的 Graphics2D 对象复制到备份变量中,然后单击撤消按钮,我将用备份对象替换当前对象。不幸的是,这不起作用。

我尝试了以下方法:

在 mousePressed 方法中,我将图形的当前值分配给备份变量。

addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
graphicsBackup = graphics.create();
oldX = e.getX();
oldY = e.getY();
}
});

在撤消方法中,我尝试将备份变量的引用分配给原始对象。

public void undo() {
graphics = graphicsBackup;
repaint();
}

在第二次尝试中,我使用了 AffineTransform 对象。我在 keyPressed 方法中调用 getTransform 来获取当前状态,然后在 undo 方法中调用 setTransform 。那也没用。您对它如何运作有什么建议吗?

<小时/>

解决方案:(添加了一些背景等附加方法)

class DrawPad extends JComponent {

private Image image;
private Image background;
private Graphics2D graphics;
private int currentX, currentY, oldX, oldY;
private final SizedStack<Image> undoStack = new SizedStack<>(12);

public DrawPad() {
setDoubleBuffered(false);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
saveToStack(image);
oldX = e.getX();
oldY = e.getY();
}
});

addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
currentX = e.getX();
currentY = e.getY();
if (graphics != null) {
graphics.drawLine(oldX, oldY, currentX, currentY);
}
repaint();
oldX = currentX;
oldY = currentY;
}
});
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null) {
image = createImage(getSize().width, getSize().height);
graphics = (Graphics2D) image.getGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}

public void clear() {
if (background != null) {
setImage(copyImage(background));
} else {
graphics.setPaint(Color.white);
graphics.fillRect(0, 0, getSize().width, getSize().height);
graphics.setPaint(Color.black);
}
repaint();
}

public void undo() {
if (undoStack.size() > 0) {
setImage(undoStack.pop());
}
}

private void setImage(Image img) {
graphics = (Graphics2D) img.getGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setPaint(Color.black);
image = img;
repaint();
}

public void setBackground(Image img) {
background = copyImage(img);
setImage(copyImage(img));
}

private BufferedImage copyImage(Image img) {
BufferedImage copyOfImage = new BufferedImage(getSize().width, getSize().height, BufferedImage.TYPE_INT_RGB);
Graphics g = copyOfImage.createGraphics();
g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
return copyOfImage;
}

private void saveToStack(Image img) {
undoStack.push(copyImage(img));
}

public void red() {
graphics.setPaint(Color.red);
repaint();
}

public void black() {
graphics.setPaint(Color.black);
repaint();
}

public void magenta() {
graphics.setPaint(Color.magenta);
repaint();
}

public void blue() {
graphics.setPaint(Color.blue);
repaint();
}

public void green() {
graphics.setPaint(Color.green);
repaint();
}
}

堆栈大小:

public class SizedStack<T> extends Stack<T> {

private final int maxSize;

public SizedStack(int size) {
super();
this.maxSize = size;
}

@Override
public Object push(Object object) {
while (this.size() > maxSize) {
this.remove(0);
}
return super.push((T) object);
}
}

最佳答案

不久前我自己实现了一个绘图程序。以下是我实现撤消/重做的方法:

我有两堆。 “撤消”堆栈和“重做”堆栈。每次用户绘制一些内容时,我都会这样做:

  1. 在将绘制的图形应用到图像之前,我将图像保存到“撤消”堆栈。
  2. 应用绘制的图形后,我再次将图像保存到“撤消”堆栈中。

例如,如果用户想要画一条线,我会在将线应用到图像之前将当前图像保存到堆栈中。应用该行后,我再次将其保存到堆栈中。

当用户按下“撤消”时,我只需从“撤消”堆栈中弹出顶部图像,并将其绘制到屏幕上。然后我将其放入“重做”堆栈中。

当用户按下“重做”时,“重做”堆栈中的顶部图像将弹出并应用到绘图区域,并放在“撤消”堆栈的顶部(相反的操作)。

编辑:为了将图像插入堆栈(堆栈中的所有对象都不会引用同一对象),您需要首先将图像复制到新图像。像这样的东西(细节可能不准确):

void saveToStack(BufferedImage img){ // makes a copy of img and puts on stack.
BufferedImage imageForStack = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
Graphics2D g2d = imageForStack.createGraphics();
g2d.drawImage(img, 0, 0, null);
undoStack.push(imageForStack);
}

希望这有帮助。

关于java - 绘画程序的撤消方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23608166/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com