最近我一直致力于一个用空的彩色方块绘制区域的程序。它们在屏幕上的位置基于文本文件中的值1和2。 1s应该制作红色盒子,2s应该制作绿色盒子。但是,当我运行程序时,只绘制了红色框。我做了一些测试,发现重绘方法只被调用两次(有时由于某种原因),即使文件中有近300个值,并且repaint()
应该为每个值调用一次。这是我的代码:
public class MAP extends JFrame {
public static void main(String[] args) throws IOException {
MAP map = new MAP();
}
Shape shape;
int x = -32;
int y = 0;
ArrayList<Shape> shapes = new ArrayList<Shape>();
Graphics2D g2;
Color coulor = null;
private class PaintSurface extends JComponent {
public PaintSurface() {
}
public void paint(Graphics g) {
g2 = (Graphics2D) g;
g2.setColor(coulor);
for (Shape s : shapes) {
g2.draw(s);
}
}
}
public MAP() throws FileNotFoundException, IOException {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.add(panel);
frame.setTitle("Grid Maker");
frame.setSize(400, 200);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.add(new PaintSurface(), BorderLayout.CENTER);
frame.setVisible(true);
readNextLine();
}
private void readNextLine() throws IOException {
File file = new File("map.txt");
BufferedReader in = new BufferedReader(new FileReader(file));
String line = in.readLine();
while (line != null) {
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (c == '1') {
coulor = Color.RED;
x += 32;
int smallX = x / 32;
int smallY = y / 32;
shape = new Rectangle2D.Float(x, y, 32, 32);
shapes.add(shape);
repaint();
} else if (c == '2') {
coulor = Color.GREEN;
x += 32;
int smallX = x / 32;
int smallY = y / 32;
shape = new Rectangle2D.Float(x, y, 32, 32);
shapes.add(shape);
repaint();
}
}
line = in.readLine();
x = -32;
y += 32;
}
}
}
为什么这段代码不能正常工作?
答案 0 :(得分:3)
绘画是短暂的,或无国籍的。
repaint
是对重绘经理的一个“请求”,告诉它在未来的某个时间它应该准备就绪,它应该画出屏幕的某些部分,它认为是脏。
这意味着当您使用g2.setColor(coulor)
方法调用paint
时,它正在使用它设置的最后一个值(调用paint
时)....这是可能是RED
。
Raufio是对的,你应该提供颜色信息和形状。就个人而言,我会设置第二个List
,它只包含Color
个对象,其中Shape
列表的每个索引都直接对应Color
中的Color
List
。
查看Painting in AWT and Swing,了解有关如何在Swing中进行绘画的详细信息。
现在,到了狡猾的部分;)
建议不要覆盖paint
。这有很多原因,paint
负责调用一些重要的方法,包括执行非常重要任务的paintChildren
和paintComponent
。
相反,您应该覆盖paintComponent
(并确保拨打super.paintComponent
)
查看Performing Custom Painting了解详情。
使用粗略示例进行更新
所以这是我正在谈论的一个粗略的例子......
public class TestPainting {
public static void main(String[] args) {
new TestPainting();
}
public TestPainting() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PaintingPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintingPane extends JPanel {
private static final int WIDTH = 200;
private static final int HEIGHT = 200;
private List<Shape> shapes;
private List<Color> colors;
public PaintingPane() {
shapes = new ArrayList<>(25);
colors = new ArrayList<>(25);
for (int index = 0; index < (int) Math.round(Math.random() * 100); index++) {
int x = (int) Math.round(Math.random() * (WIDTH * 0.75f));
int y = (int) Math.round(Math.random() * (HEIGHT * 0.75f));
int width = (int) Math.round(Math.random() * (WIDTH * 0.25f));
int height = (int) Math.round(Math.random() * (HEIGHT * 0.25f));
if (width < 5) {
width = 5;
}
if (height < 5) {
height = 5;
}
if (x + width > WIDTH) {
x -= width - WIDTH;
}
if (y + height > HEIGHT) {
y -= height - HEIGHT;
}
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
Color color = ((int)Math.round(Math.random() * 2)) == 1 ? Color.RED : Color.GREEN;
shapes.add(new Rectangle(x, y, width, height));
colors.add(color);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (int index = 0; index < shapes.size(); index++) {
g2d.setColor(colors.get(index));
g2d.draw(shapes.get(index));
}
g2d.dispose();
}
}
}
答案 1 :(得分:3)
只是为了添加其他答案,这里有一段代码(基于你的代码)看起来已经好多了(但仍有一些问题,但你还没有):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class MAP extends JFrame {
public static void main(String[] args) throws IOException {
MAP map = new MAP();
}
public static class ColoredShape {
private Shape shape;
private Color color;
public ColoredShape(Shape shape, Color color) {
super();
this.shape = shape;
this.color = color;
}
public Shape getShape() {
return shape;
}
public Color getColor() {
return color;
}
}
int x = -32;
int y = 0;
List<ColoredShape> shapes = new ArrayList<ColoredShape>();
Graphics2D g2;
private class PaintSurface extends JComponent {
public PaintSurface() {
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g2 = (Graphics2D) g;
for (ColoredShape s : shapes) {
g2.setColor(s.getColor());
g2.draw(s.getShape());
}
}
}
public MAP() throws FileNotFoundException, IOException {
JFrame frame = new JFrame();
frame.setTitle("Grid Maker");
frame.setSize(400, 400);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.add(new PaintSurface(), BorderLayout.CENTER);
frame.setVisible(true);
readNextLine();
}
private void readNextLine() throws IOException {
BufferedReader in = new BufferedReader(new StringReader("11121\n1221\n2212\n221121\n111221\n11221\n222\n2222\n"));
String line = in.readLine();
while (line != null) {
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
Color color = null;
if (c == '1') {
color = Color.RED;
} else if (c == '2') {
color = Color.GREEN;
}
if (color != null) {
shapes.add(new ColoredShape(new Rectangle2D.Float(x, y, 32, 32), color));
x += 32;
repaint();
}
}
line = in.readLine();
x = -32;
y += 32;
}
}
}
答案 2 :(得分:0)
我看到的第一件事是你一次只为一种颜色着色。所以这里:
public void paint(Graphics g) {
g2 = (Graphics2D) g;
g2.setColor(coulor); //set the drawing color
for (Shape s : shapes) {
g2.draw(s); //draw in that color
}
}
当您想要以不同方式着色时,所有形状都以相同的颜色绘制。我认为更好的做法是将所有形状添加到列表中,跟踪其颜色,并调用repaint()
一次。另外,我会将paint方法更改为以下效果:
public void paint(Graphics g) {
g2 = (Graphics2D) g;
for (Shape s : shapes) {
g2.setColor(coulor[indexOfShape]); //set the drawing color
g2.draw(s); //draw in that color
}
}
此外,仅repaint
被调用两次:它可能会抛出IOException
。尝试使用try {...} catch(IOException e) {...}
块而不是仅仅将其抛弃。类似的东西:
private void readNextLine() {
try {
File file = new File("map.txt");
BufferedReader in = new BufferedReader(new FileReader(file));
String line = in.readLine();
...
...
} catch (IOException e) {
e.printStackTrace();
}
}
如果不正确,它应该抱怨。