我的问题:graphics2D对象对ArrayList中的每个点进行重新着色。当我改变颜色时,它不会改变以前的颜色,我该怎么做?我的猜测是改变for循环在PaintApp中的交互方式,但我不确定我应该做什么。谢谢你的帮助!
我的代码:
PaintApp.java
package paint;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class PaintApp extends JPanel {
private List<List<Point>> points;
private JFrame frame = new JFrame("Sketch MSPaint");
private JMenuBar bar = new JMenuBar();
private JMenu file = new JMenu("File");
private JMenu colors = new JMenu("Colors");
private JMenuItem quit = new JMenuItem("Quit");
private JMenuItem red = new JMenuItem("Red");
private JMenuItem blue = new JMenuItem("Blue");
private JMenuItem green = new JMenuItem("Green");
private JMenuItem orange = new JMenuItem("Orange");
private JMenuItem pink = new JMenuItem("Pink");
private JMenuItem cyan = new JMenuItem("Cyan");
private JMenuItem clear = new JMenuItem("Clear");
private boolean clearBoard = false, blackColor, redColor, blueColor, greenColor, orangeColor, pinkColor, cyanColor;
public PaintApp(Dimension d) {
this.setSize(d);
this.setPreferredSize(d);
points = new ArrayList<>();
MouseAdapter ma = new MouseAdapter() {
private List<Point> currentPath;
@Override
public void mousePressed(MouseEvent e) {
currentPath = new ArrayList<>();
currentPath.add(e.getPoint());
points.add(currentPath);
}
@Override
public void mouseDragged(MouseEvent e) {
Point dragPoint = e.getPoint();
currentPath.add(dragPoint);
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
currentPath = null;
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.clearRect(0, 0, frame.getWidth(), frame.getHeight());
for (List<Point> path : points) {
Point from = null;
for (Point p : path) {
if (from != null) {
if (redColor) {
g2d.setColor(Color.red);
} else if (blueColor) {
g2d.setColor(Color.blue);
} else if (greenColor) {
g2d.setColor(Color.green);
} else if (orangeColor) {
g2d.setColor(Color.orange);
} else if (pinkColor) {
g2d.setColor(Color.pink);
} else if (cyanColor) {
g2d.setColor(Color.cyan);
} else {
g2d.setColor(Color.black);
}
g2d.drawLine(from.x, from.y, p.x, p.y);
}
from = p;
}
}
g2d.dispose();
}
public void initBar() {
bar.add(file);
file.add(clear);
clear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
points = new ArrayList<>();
repaint();
}
});
file.add(quit);
quit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
bar.add(colors);
colors.add(red);
red.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
redColor = true;
blueColor = false;
greenColor = false;
orangeColor = false;
pinkColor = false;
cyanColor = false;
repaint();
}
});
colors.add(orange);
orange.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
redColor = false;
blueColor = false;
greenColor = false;
orangeColor = true;
pinkColor = false;
cyanColor = false;
repaint();
}
});
colors.add(blue);
blue.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
redColor = false;
blueColor = true;
greenColor = false;
orangeColor = false;
pinkColor = false;
cyanColor = false;
repaint();
}
});
colors.add(green);
quit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
redColor = false;
blueColor = false;
greenColor = true;
orangeColor = false;
pinkColor = false;
cyanColor = false;
repaint();
}
});
colors.add(pink);
quit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
redColor = false;
blueColor = false;
greenColor = false;
orangeColor = false;
pinkColor = true;
cyanColor = false;
repaint();
}
});
colors.add(cyan);
quit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
redColor = false;
blueColor = false;
greenColor = false;
orangeColor = false;
pinkColor = false;
cyanColor = true;
repaint();
}
});
frame.setJMenuBar(bar);
}
public void show() {
frame.add(this);
initBar();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
Main.java
package paint;
import java.awt.Dimension;
public class Main {
public static void main(String[] args) {
PaintApp app = new PaintApp(new Dimension(700,700));
app.show();
}
}
我看到的最简单的解决方案,如果你不想给它一个"撤消";功能是绘制到BufferedImage,然后在paintComponent
覆盖(而不是paint
-neverpaint
(内显示相同的BufferedImage。这样,以前绘制的线将一直保留,直到用新实例替换BufferedImage为止。
否则,如果你绝对不能走这条路,那么创建一个新的自定义类,一个包含Line2D
或其他Shape类型对象和Color的类,在用户绘制时创建这些对象,将它们存储到这样的对象列表中,然后在(再次(paintComponent
覆盖中使用它们进行绘制。通过这种方式,您可以将每条线(或其他形状(与"颜色"相关联,并且这种关联将持续存在。
如上所述,我还建议不要覆盖paint
,而应该覆盖paintComponent
,因为后者允许在您决定制作动画时自动进行双缓冲,而且您也不会有干扰组件的子组件和边界绘制的风险,而在覆盖paint
时,您可能会有这种风险。当然,在重写中调用super.paintComponent(g)
方法,通常是在它的第一行。