0

I'm trying to code a picture viewer application using Java Swing. My little application has a JMenuItem importItem in order to select an image. The problem in this app. is that when you add only one picture it doesn't show up, so you should add two or more pictures. I think the problem is inside the importItem actionPerformed() method but I don't know where is it exactly.

Any idea how to fix it?

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class MainFrame2 extends JFrame implements ActionListener{
private JPanel northPanel,principalPanel,centerPanel;
private JButton nextButton,previousButton;
private int counter = 1;
private JFileChooser jFileChooser;
private ArrayList<JPanel> picturesPanels;
private ArrayList<BufferedImage> pictures;

public MainFrame2() {
    setSize(600,600);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    northPanel = new JPanel(new FlowLayout());
    nextButton = new JButton(">>");
    nextButton.addActionListener(this);
    previousButton = new JButton("<<");
    previousButton.addActionListener(this);
    northPanel.add(previousButton);
    northPanel.add(nextButton);

    picturesPanels = new ArrayList<>();
    pictures = new ArrayList<>();

    centerPanel = new JPanel(new CardLayout());
    principalPanel = new JPanel(new BorderLayout());
    principalPanel.add(northPanel,BorderLayout.NORTH);
    principalPanel.add(centerPanel,BorderLayout.CENTER);
    setContentPane(principalPanel);
    setJMenuBar(myMenu());

    jFileChooser = new JFileChooser();
    //jFileChooser.setFileFilter(new PictureFilter());
    jFileChooser.setMultiSelectionEnabled(true);

    setMinimumSize(new Dimension(300,300));
    setVisible(true);
}

private JMenuBar myMenu() {
    JMenuBar jMenuBar = new JMenuBar();
    JMenu fileMenu = new JMenu("File");
    JMenuItem importItem = new JMenuItem("Import pictures");
    fileMenu.add(importItem);
    ////////////////Setting Up importItem///////////////////
    importItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (jFileChooser.showOpenDialog(MainFrame2.this)
                    == JFileChooser.APPROVE_OPTION) {
                File [] files = jFileChooser.getSelectedFiles();
                for (int i=0;i<files.length;i++) {
                    try {
                        pictures.add(ImageIO.read(new 
                File(files[i].getPath())));
                    } catch (IOException e1) {
                        System.out.println("Error loading image");
                    }
                }
                picturesPanels.clear();
                for (BufferedImage image:pictures) {
                    picturesPanels.add(new JPanel() {
                        @Override
                        protected void paintComponent(Graphics g) {
                            super.paintComponent(g);
                            int original_width = image.getWidth();
                            int original_height = image.getHeight();
                            int bound_width = getWidth();
                            int bound_height = getHeight();
                            int new_width = original_width;
                            int new_height = original_height;

                            if (original_width > bound_width) {
                                new_width = bound_width;
                                new_height = (new_width * original_height) / 
          original_width;
                            }
                            if (new_height > bound_height) {
                                new_height = bound_height;
                                new_width = (new_height * original_width)/ 
          original_height;
                            }
                            g.drawImage(image,(getWidth()-new_width)/2
                                    ,(getHeight()- 
            new_height)/2,new_width,new_height,this);
                        }
                    });
                }
                for (int i=0;i<picturesPanels.size();i++) {
                    centerPanel.add(picturesPanels.get(i),""+(i+1));
                }
            }
        }
    });
    jMenuBar.add(fileMenu);
    return jMenuBar;
}

@Override
public void actionPerformed(ActionEvent e) {
    CardLayout cardLayout = (CardLayout)centerPanel.getLayout();
    if (e.getSource() == nextButton) {
        counter++;
        if (counter>pictures.size()) {
            counter = 1;
        }
        cardLayout.show(centerPanel,""+counter);
    }
    if (e.getSource() == previousButton) {
        counter--;
        if (counter<1) {
            counter = pictures.size();
        }
        cardLayout.show(centerPanel,""+counter);
    }
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            new MainFrame2();
        }
    });
}
}
7
  • Did you just write a single sentence with 117 words? Commented Apr 13, 2018 at 17:53
  • hah i just tried to explain the problem more Commented Apr 13, 2018 at 17:59
  • One thing I see, is that you don't clear out pictures but then each time the user adds pictures, you loop through pictures and add a new JPanel to picturePanels. I would think this would cause a repeat of any previously loaded pictures. Then when you add them to the centerPanel you haven't removed the previous ones, so there might be multiple picturePanels with the same constraints. Commented Apr 13, 2018 at 18:18
  • Also you should consider making a PicturePanel class that extends JPanel and implements an BufferedImage image; class variable and set that in the constructor, like picturePanels.add(new PicturePanel(image));. Commented Apr 13, 2018 at 18:22
  • @bcr666 thanks man i solved multiple picturePanels with the same constraints jus with adding picturesPanels.clear(); before this loop` for (BufferedImage image:pictures)` Commented Apr 13, 2018 at 18:26

1 Answer 1

1

Here is some code that works for me. There are several code optimizations.

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ImageLoaderTest extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;
    private JButton nextButton, previousButton;
    private CardLayout cards = new CardLayout();
    private JPanel centerPanel = new JPanel(cards);
    private JFileChooser jFileChooser;

    public ImageLoaderTest() {
        setSize(600, 600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JPanel northPanel = new JPanel(new FlowLayout());
        nextButton = new JButton(">>");
        nextButton.addActionListener(this);
        previousButton = new JButton("<<");
        previousButton.addActionListener(this);
        northPanel.add(previousButton);
        northPanel.add(nextButton);

        JPanel principalPanel = new JPanel(new BorderLayout());
        principalPanel.add(northPanel, BorderLayout.NORTH);
        principalPanel.add(centerPanel, BorderLayout.CENTER);
        setContentPane(principalPanel);
        setJMenuBar(myMenu());

        jFileChooser = new JFileChooser();
        // jFileChooser.setFileFilter(new PictureFilter());
        jFileChooser.setMultiSelectionEnabled(true);

        setMinimumSize(new Dimension(300, 300));
        setVisible(true);
    }

    private JMenuBar myMenu() {
        JMenuBar jMenuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem importItem = new JMenuItem("Import pictures");
        fileMenu.add(importItem);
        //////////////// Setting Up importItem///////////////////
        importItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (jFileChooser.showOpenDialog(ImageLoaderTest.this) == JFileChooser.APPROVE_OPTION) {
                    File[] files = jFileChooser.getSelectedFiles();
                    for (int i = 0; i < files.length; i++) {
                        try {
                            BufferedImage image = ImageIO.read(new File(files[i].getPath())); // Assigned image to variable, not needed but makes next line cleaner.
                            centerPanel.add(new PicturePanel(image)); // add the picture directly to the panel, no need to create a list. Also used a custom PicturePanel
                            cards.next(centerPanel); // automatically press the next button so that we see the picture loaded.
                        } catch (IOException e1) {
                            System.out.println("Error loading image");
                        }
                    }
                }
            }
        });
        jMenuBar.add(fileMenu);
        return jMenuBar;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == nextButton) {
            cards.next(centerPanel); // cleaned up code. No need to implement a counter when .next() will do. Unless you want to jump around
        }
        if (e.getSource() == previousButton) {
            cards.previous(centerPanel); // cleaned up code. No need to implement a counter when .previous() will do. Unless you want to jump around
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ImageLoaderTest();
            }
        });
    }
}

class PicturePanel extends JPanel {
    private static final long serialVersionUID = 1L;
    protected BufferedImage image = null;

    public PicturePanel(BufferedImage image) {
        super();
        this.image = image;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int original_width = image.getWidth();
        int original_height = image.getHeight();
        int bound_width = getWidth();
        int bound_height = getHeight();
        int new_width = original_width;
        int new_height = original_height;

        if (original_width > bound_width) {
            new_width = bound_width;
            new_height = (new_width * original_height) / original_width;
        }
        if (new_height > bound_height) {
            new_height = bound_height;
            new_width = (new_height * original_width) / original_height;
        }
        g.drawImage(image, (getWidth() - new_width) / 2, (getHeight() - new_height) / 2,
                new_width, new_height, this);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.