0

I'm trying to flip through multiple images using previous and next button. Currently, the layout is:

enter image description here

and this is my code:

 public void createWalkthrough() {
  if(currentframe != null) {
        currentframe.setVisible(true);
        return;
    }

  currentframe = new JFrame("Getting Started");

  JPanel imagePanel = new JPanel();
  imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

  imageArea = new JLabel();
  imagePanel.add(imageArea);

  JButton previousButton = new JButton("Previous");
  previousButton.addActionListener(this);
  previousButton.setActionCommand("Previous");

  JButton nextButton = new JButton("Next");
  nextButton.addActionListener(this);
  nextButton.setActionCommand("Next");

  JPanel panelButtons = new JPanel();
  panelButtons.setLayout(new BoxLayout(panelButtons, BoxLayout.LINE_AXIS));
  panelButtons.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
  panelButtons.add(Box.createRigidArea(new Dimension(10, 0)));
  panelButtons.add(Box.createHorizontalGlue());
  panelButtons.add(previousButton);
  panelButtons.add(nextButton);

  currentframe.setSize(439, 548);
  currentframe.setResizable(false);

  Container pane = currentframe.getContentPane();
  pane.add(imagePanel, BorderLayout.CENTER);
  currentframe.add(panelButtons, BorderLayout.PAGE_END);

  currentframe.setVisible(true);

  currentframe.requestFocusInWindow();
}       

public void displayImage(int index) {
  File[] imagesList = getImages();
  File imageName = imagesList[index];
  ImageIcon icon = new ImageIcon(imageName.getAbsolutePath());
  Image image = icon.getImage().getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), Image.SCALE_SMOOTH);
  imageArea.setIcon(new ImageIcon(image));
}

public File[] getImages() {
  File folder = new File("/Users/jwh/Desktop/img");
  File[] listofImages = folder.listFiles();
  return listofImages;
}

@Override 
public void actionPerformed(ActionEvent e) {
    if(base == null) {
        return;
    }

    String selected = e.getActionCommand();

    if(selected.equals("Previous")) {
        pos = pos - 1;
        if(pos < 0) {
            pos = 0;
        }

        displayImage(pos);
    } else if(selected.equals("Next")) {
        pos = pos + 1;
        if(pos >= getImages().length) {
            pos = getImages().length;
        }

        displayImage(pos);
    }
}

I'm not sure what I am doing wrong. I feel like I keep going around in circles by trying different things on different StackOverflow posts.

The error that I am currently getting is:

"Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: 
    Width (0) and height (0) must be non-zero"

Any help would be greatly appreciated. Thank you!!

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
jaewhyun
  • 71
  • 2
  • 11
  • 1
    1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) Post the entire stack trace, and use code formatting for it as well. – Andrew Thompson Apr 15 '18 at 20:24
  • As @AndrewThompson says above. Also indicate in your posted code which line throws the exception – Hovercraft Full Of Eels Apr 15 '18 at 20:25
  • 1
    I'm guessing that it's this line `Image image = icon.getImage().getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), Image.SCALE_SMOOTH);`, and that it's because your JLabel is currently sized [0, 0] as it has no image in it to start. Why not give the JLabel a blank image of your own creation to start with so that its size is not 0,0? – Hovercraft Full Of Eels Apr 15 '18 at 20:26
  • 1
    @HovercraftFullOfEels *"Why not give the JLabel a blank image of your own creation to start with"* Good idea, then the code can `pack()` the GUI to correct size & avoid guesswork like: `currentframe.setSize(439, 548);` – Andrew Thompson Apr 15 '18 at 20:28
  • Thank you so much for the suggestions/advice! – jaewhyun Apr 15 '18 at 22:01

1 Answers1

0

Your primary problem comes down to the compounding nature of your layouts and misunderstanding of the default layouts...

JPanel imagePanel = new JPanel();
imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

imageArea = new JLabel();
imagePanel.add(imageArea);

imagePanel, by default, is using a FlowLayout, which will attempt to honour the preferredSize of the components added to it.

JLabel, by default, has a preferredSize of 0x0.

So, when you do something like...

Image image = icon.getImage().getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), Image.SCALE_SMOOTH);

you're actually passing 0x0 to the getScaledInstance method.

While there are number of ways to fix it, the simplest would be to use a layout manager which wants to fill the available space, like BorderLayout...

JPanel imagePanel = new JPanel(new BorderLayout());
imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

imageArea = new JLabel();
imagePanel.add(imageArea);

Feedback...

Okay, a number of small issues...

getScaledInstance does not produce the best result, nor is the fastest way to scale an image. Now, if you'd prefer not to use a library, like imgscalr, you could use something like Java: maintaining aspect ratio of JPanel background image and Quality of Image after resize very low -- Java to scale the images

It's some what of a personal thing, but I don't like the ImageIcon API, it doesn't provide feedback about why an image might not have been loaded and doesn't support a large range of image formats.

Personally, I prefer to use the ImageIO API instead. See Reading/Loading an Image

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366