Search code examples
javabufferedimagepaintcomponentppm

BufferedImage How do I stop all the images from having the color from the last one painted


I'm using Java, and I'm reading from a ppm file, code P3.

P3
# The P3 means colors are in ASCII, then 3 columns and 2 rows,
# then 255 for max color, then RGB triplets
3 2
255
255   0   0     0 255   0     0   0 255
255 255   0   255 255 255     0   0   0  

My objective with this file is to paint 6 images with the rgb values above, however all the images always stay the same color as the last rgb values. Here's my code:

public class Window2 extends JFrame {

    public JMenuBar menubar;
    public JMenuItem importFile;
    public Scanner filePath;
    StringTokenizer tokens = null;
    ArrayList<BufferedImage> image = new ArrayList<>();
    int[][][] images;
    JPanel panelDown = new JPanel();
    MyPanel myPanel;
    Color myColor;

    int[] coords = new int[2];
    int i = 0, j = 0;

    public class MyPanel extends JPanel {

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            for (BufferedImage image1 : image) {
                g.drawImage(image1, 0, 0, null);
            }

        }
    }

    public Window2() {
        super("Exercise 2");
        menubar = new JMenuBar();
        setLayout(new BorderLayout());
        JPanel panelBar = new JPanel();
        add(panelBar, BorderLayout.NORTH);
        add(panelDown, BorderLayout.CENTER);
        importFile = new JMenuItem("Import", 'I');
        panelBar.add(menubar);
        menubar.add(importFile);
        importFile.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                FileDialog fd = new FileDialog(Window2.this, "Import Maze", FileDialog.LOAD);
                fd.setFile(".txt");
                fd.setLocation(Window2.this.getX() + 100, Window2.this.getY() + 100);
                fd.show();
                if (!fd.getFile().endsWith(".txt")) {
                    JOptionPane.showMessageDialog(Window2.this, "Wrong file extension", "Error", JOptionPane.WARNING_MESSAGE);
                } else {
                    File theFile = new File(fd.getDirectory() + "\\" + fd.getFile());
                    try {
                        filePath = new Scanner(theFile);
                    } catch (FileNotFoundException ex) {
                        Logger.getLogger(Window2.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    images = readFile(filePath);
                    panelDown.setLayout(new GridLayout(coords[0], coords[1]));
                    int z=0;
                    for (int k = 0; k < coords[0]; k++) {
                        for (int l = 0; l < coords[1]; l++) {
                            int red = images[k][l][0];
                            int green = images[k][l][1];
                            int blue = images[k][l][2];
                            myPanel = new MyPanel();
                            panelDown.add(myPanel);
                            image.add(new BufferedImage(30, 30, BufferedImage.TYPE_INT_ARGB));
                            myColor = new Color(red,green,blue,255);
                            for (int i = 0; i < 30; i++) {
                                for (int j = 0; j < 30; j++) {
                                    image.get(z).setRGB(i, j, myColor.getRGB());  
                                }
                            }
                            z++;
                        }
                    }
                    myPanel.repaint();
                }
            }
        });

        setSize(500, 500);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

There is one method missing here, it's the readFile. It returns an array[][][], number of rows, columns and the rgb values respectifully. Any ideia on how I can fix this?


Solution

  • MyPanel is painting ALL the images every time it is painted, so each instance of MyPanel is showing the LAST image which was added to the images List...

    public class MyPanel extends JPanel {
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            for (BufferedImage image1 : image) {
                g.drawImage(image1, 0, 0, null);
            }
    
        }
    }
    

    You then create and add an instance of MyPanel for each image...

    myPanel = new MyPanel();
    panelDown.add(myPanel);
    

    But, MyPanel is painting ALL the image on top of each other, so only the last image added to the List is displayed...

    Instead, try passing the individual image to be painted to MyPanel

    public class MyPanel extends JPanel {
    
        private BufferdImage img;
    
        public MyPanel(BufferdImage img) {
            this.img = img;
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.drawImage(img, 0, 0, this);
        }
    }
    

    And then when you build the image, pass a reference to the MyPanel instance, for example.

    for (int k = 0; k < coords[0]; k++) {
        for (int l = 0; l < coords[1]; l++) {
            //...
            BufferedImage img = new BufferedImage(30, 30, BufferedImage.TYPE_INT_ARGB);
            image.add(img);
            myColor = new Color(red,green,blue,255);
            for (int i = 0; i < 30; i++) {
                for (int j = 0; j < 30; j++) {
                    image.get(z).setRGB(i, j, myColor.getRGB());  
                }
            }
            myPanel = new MyPanel(img);
            panelDown.add(myPanel);
            z++;
        }
    }