我正在JFrame
上绘制一些物体,例如圆圈,矩形和它们之间的弧线。
我想知道如何实现 Undo 按钮,记住我发现的那些按钮是针对文本字段并在其中写入的。
我没有要显示的代码,我希望收到有关如何实现它的建议。是否可以“注册”最后发生的事件然后将其删除?
我有一个关于删除圈子的非常简单的代码。它只适用于他们,我知道这是完全错误的,因为我可以有其他事件,如矩形绘制或它们之间的弧。
感谢任何帮助。
答案 0 :(得分:5)
您可以将Shape个对象存储在List
中,让面板从此List
中绘制每个形状。
"撤消" action只是移除最后一个元素并重新绘制面板。
以下示例包含用于在随机位置创建矩形和椭圆的按钮,以及着名的"撤消"按钮让你明白了。
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
public class DrawingUndo {
List<Shape> shapes = new ArrayList<>();
public DrawingUndo() {
final Random randomizer = new Random();
JFrame frame = new JFrame("Undoable drawings");
JToolBar bar = new JToolBar();
final JPanel undoPanel = new UndoPanel();
JButton addRectangleButton = new JButton("Rectangle");
addRectangleButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
int randomX = 5 + randomizer.nextInt(100);
int randomY = 5 + randomizer.nextInt(100);
Rectangle shape = new Rectangle();
shape.setBounds(randomX, randomY, 30, 20);
shapes.add(shape);
undoPanel.repaint();
}
});
JButton addEllipseButton = new JButton("Ellipse");
addEllipseButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
int randomX = 5 + randomizer.nextInt(100);
int randomY = 5 + randomizer.nextInt(100);
Ellipse2D shape = new Ellipse2D.Double(randomX, randomY, 80, 30);
shapes.add(shape);
undoPanel.repaint();
}
});
JButton undoButton = new JButton("Undo");
undoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (!shapes.isEmpty()) {
shapes.remove(shapes.size() - 1);
undoPanel.repaint();
}
}
});
bar.add(addRectangleButton);
bar.add(addEllipseButton);
bar.add(Box.createHorizontalGlue());
bar.add(undoButton);
frame.add(bar, BorderLayout.NORTH);
frame.add(undoPanel, BorderLayout.CENTER);
frame.setSize(400, 200);
frame.setVisible(true);
}
public static void main(final String[] args) {
new DrawingUndo();
}
private class UndoPanel extends JPanel {
@Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Shape shape : shapes) {
g2d.draw(shape);// or g2d.fill(shape) to have its interior filled
}
}
}
}
请注意,Shape
并不像颜色那样。
如果您需要这样的东西,请创建一个包含Shape
和其他所需参数的包装类,并使用此类对象的列表而不是简单的Shape
对象。
答案 1 :(得分:0)
正如@fujy所说,看看Command设计模式(https://sourcemaking.com/design_patterns/command)。高级别的想法是,每次要更改某些内容时,都会创建命令。每个命令都有两个方法 do 和 undo 。执行后,您应该将命令存储在队列(或其他一些数据结构)中。通过按时间顺序遍历命令,您可以执行撤消并实现按钮。 命令对象应包含有关如何执行操作以及如何重做操作的所有信息。例如,它应该包含 newFieldValue , oldFieldValue ...还有其他方法可以实现 undu 概念,但我觉得这个很简单和通用 - 它不依赖于您使用的技术。