1

最近我一直在研究一个用空的彩色方块绘制区域的程序。它们在屏幕上的位置基于文本文件中的值 1 和 2。1s 应该制作红色盒子,2s 应该制作绿色盒子。但是,当我运行程序时,只绘制了红色框。我做了一些测试,发现 repaint 方法只被调用了两次(有时出于某种原因一次),即使文件中有接近 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;
        }
    }
}

为什么这段代码不能正常工作?

4

3 回答 3

3

绘画是短暂的,或无状态的。

repaint是向重绘管理器发出的“请求”,告诉它应该在未来的某个时间,当它准备好时,它应该绘制它认为是脏的屏幕的某些部分。

这意味着当你调用g2.setColor(coulor)你的paint方法时,它使用的是它设置为的 LAST 值(当paint被调用时)......这可能是RED.

Raufio 是对的,您应该提供颜色信息以及形状。就个人而言,我会设置一个List只包含Color对象的第二个,其中列表的每个索引都Shape直接对应ColorColor List.

查看在 AWT 和 Swing中的绘画,了解更多关于如何在 Swing 中进行绘画的详细信息。

现在,到发牢骚的部分;)

不建议覆盖paint. 这有很多原因,paint负责调用一些重要的方法,包括paintChildrenand paintComponent,它们执行非常重要的任务。

相反,您应该覆盖paintComponent(并确保您调用super.paintComponent

查看执行自定义绘画以获取更多详细信息。

用粗略的例子更新

所以这是我所说的一个粗略的例子......

在此处输入图像描述

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();

        }
    }
}
于 2013-02-10T23:49:40.280 回答
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;
        }
    }
}
于 2013-02-10T23:52:40.280 回答
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();
    }
}

如果阅读不正确,它应该抱怨一些事情。

于 2013-02-10T23:08:42.733 回答