1

最近、空の色付きの四角形で領域をペイントするプログラムに取り組んでいます。画面上のそれらの位置は、テキスト ファイルの値 1 と 2 に基づいています。1 は赤い箱を作り、2 は緑の箱を作るはずです。しかし、プログラムを実行すると、赤いボックスだけがペイントされます。repaint()私はいくつかのテストを行い、ファイルに 300 近くの値があり、値ごとに 1 回呼び出す必要があるにもかかわらず、repaint メソッドが 2 回 (何らかの理由で 1 回) しか呼び出されていないことがわかりました。これが私のコードです:

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

他の答えに追加するために、ここに(あなたのコードに基づいて)すでにはるかに良く見えるコードがあります(まだいくつかの問題がありますが、あなたはまだそこにいません):

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 に答える
3

ペイントは一時的、つまりステートレスです。

repaint将来のある時点で、準備ができたときに、画面の一部をペイントする必要があることを伝えるために、再描画マネージャーに対して行われる「要求」です。

これは、メソッドを呼び出すときにg2.setColor(coulor)paint(が呼び出されたときに) に設定された LAST 値を使用していることを意味します。paintこれはおそらくRED.

Raufio の言うとおりです。形状とともに色情報を提供する必要があります。個人的にListは、リストColorの各インデックスが.ShapeColorColor List

AWT と Swingでのペイントを参照して、Swing でのペイントの仕組みの詳細を確認してください。

さて、気まぐれな部分に;)

オーバーライドすることはお勧めしませんpaint。これには多くの理由があり、非常に重要なタスクを実行するやpaintなど、いくつかの重要なメソッドを呼び出す責任があります。paintChildrenpaintComponent

代わりに、オーバーライドする必要があります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 に答える
0

The first thing I see is that you are only coloring shapes one color at a time. So here:

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
    }
}

All your shapes are being drawn in the same color, when you want to color them differently. I think a better way to do things is to add all your shapes into your list, keeping track of their color, and calling repaint() once. Also, I would change the paint method to something to the effect of:

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
    }
}

Also, for repaint only being called twice: It is probably throwing an IOException. Try using a try {...} catch(IOException e) {...} block instead of just throwing it up the line. Something like:

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

It should complain about something if it isn't reading right.

于 2013-02-10T23:08:42.733 に答える