简体   繁体   English

Repaint()没有被调用

[英]Repaint() not being called

Recently I've been working on a program that paints an area with empty, colored squares. 最近,我一直在研究一个程序,该程序使用空的彩色正方形绘制区域。 Their locations on the screen are based off of the values 1 and 2 in a text file. 它们在屏幕上的位置基于文本文件中的值1和2。 1s are supposed to make red boxes, and 2s are supposed to make green boxes. 1应该被做成红色的盒子,而2应该被做成绿色的盒子。 However, when I run the program, only red boxes are painted. 但是,当我运行该程序时,只绘制了红色框。 I did some testing and found out that the repaint method is only being called twice(once sometimes for some reason), even though there are close to 300 values in the file, and repaint() should be called once for every value. 我进行了一些测试,发现repaint方法仅被调用两次(有时由于某种原因有时被调用),即使文件中有接近300个值,并且应该为每个值调用一次repaint() Here is my code: 这是我的代码:

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

Why isn't this code working properly? 为什么此代码无法正常工作?

Painting is transient, or stateless. 绘画是短暂的或无状态的。

repaint is a "request" made to the repaint manager to tell it that it should, at some time in the future, when it's ready, it should paint some portion of the screen, that it deems to be dirty. repaint是对重新绘制管理器发出的“请求”,告诉它应该在将来的某个时候准备就绪时绘制屏幕的某些部分,认为它是脏的。

This means that when you call g2.setColor(coulor) in you paint method, it is using the LAST value that it was set to (when paint is called)....which is probably RED . 这意味着,当您在paint方法中调用g2.setColor(coulor)时,它使用的是设置为LAST的值(当paint被调用时)....这可能是RED

Raufio is right, you should be providing color information along with the shapes. Raufio是正确的,您应该随形状一起提供颜色信息。 Personally, I would set up a second List which just contained Color objects, where each index of the Shape list corresponded directly to the Color in the Color List . 就个人而言,我会成立第二个List刚刚包含Color的对象,其中的每个索引Shape列表直接对应的ColorColor List

Check out Painting in AWT and Swing for more details on how painting in works in Swing. 查阅AWT和Swing中的绘画,以获得有关Swing中绘画工作原理的更多详细信息。

Now, to the whiny part ;) 现在,到了令人苦恼的部分;)

It is not recommended to override paint . 不建议覆盖paint There are lots of reasons for this, paint is responsible for calling a number of important methods, including paintChildren and paintComponent , which perform very important tasks. 造成这种情况的原因很多, paint负责调用许多重要的方法,包括paintChildrenpaintComponent ,它们执行非常重要的任务。

Instead, you should override paintComponent (and make sure you call super.paintComponent ) 相反,您应该重写paintComponent (并确保调用super.paintComponent

Check out Performing Custom Painting for more details. 请查看执行自定义绘画以获取更多详细信息。

Update with rough example 用粗略的例子更新

So this is a rough example of what I'm talking about... 所以这是我在说的一个粗糙的例子...

在此处输入图片说明

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

        }
    }
}

Just to add to other answers, here is a piece of code (based on yours) which looks already a lot better (yet there are still some issues, but you are not there yet): 只是为了增加其他答案,以下是一段代码(基于您的代码),看起来看起来已经好了很多(但是仍然存在一些问题,但是您还不存在):

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

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. 我认为一种更好的处理方法是将所有形状添加到列表中,跟踪其颜色,然后一次调用repaint() Also, I would change the paint method to something to the effect of: 另外,我将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
    }
}

Also, for repaint only being called twice: It is probably throwing an IOException . 另外,对于repaint仅被调用两次:它可能抛出IOException Try using a try {...} catch(IOException e) {...} block instead of just throwing it up the line. 尝试使用try {...} catch(IOException e) {...}块,而不是仅仅将其扔在一行上。 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. 如果阅读不正确,它应该抱怨一些东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM