1

I already checked this duplicate question and other similar ones and it didn't help. I am trying to add an png to a button when it is clicked. The program is a variable sized tic-tac-toe game for school.

Right now I have:

private ImageIcon X_MARK = new ImageIcon("x.png");
private ImageIcon O_MARK = new ImageIcon("o.gif");
private JButton[][] cells;

...

    cells = new JButton[size][size];
    JPanel board = new JPanel(new GridLayout(size, size));
    board.setBorder(new LineBorder(Color.BLACK, 1));

    ButtonListener listener = new ButtonListener();

    for (int i = 0; i < size; i++)
        for (int j = 0; j < size; j++) {
            cells[i][j] = new JButton();
            cells[i][j].addActionListener(listener);
            board.add(cells[i][j]);
        }
    JFrame ttt = new JFrame();
    ttt.add(board);
    ttt.setTitle("Show GUI Components");
    ttt.setSize(60*size, 60*size);
    ttt.setLocation(0, 0);
    ttt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ttt.setVisible(true);

...

class ButtonListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {

        int i, j;

        for (i = 0; i < size; i++)
            for (j = 0; j < size; j++)
                if (e.getSource() == cells[i][j]) {
                    if ((i + j) % 2 == 0) {
                        cells[i][j].setBackground(Color.GREEN);
                        cells[i][j].setIcon(X_MARK);
                    } else {
                        cells[i][j].setBackground(Color.CYAN);
                        cells[i][j].setIcon(O_MARK);
                    }
                }

    }
}

That is all the relevant code I think. I am using Eclipse and I have x.png and o.png in the src folder and the bin folder of the the project. I have also tried a couple of variants I have seen on SO and google searches like, new ImageIcon("C:/Users/BigBoy/workspace_1/EventDriven/src/x.png");, new ImageIcon("src/x.png");, and some other ones involving getClass().getResource among other things. I don't know what else to try. I know I've done this in the past and didn't have this much trouble.

I added .setBackground(Color.GREEN); just to make sure my clicks were registering properly and they are, the problem to me seems to be with the declaring/initializing of the ImageIcon.

NOTE: Right now my button listener just makes the checker board pattern, I will get to actually putting each player's mark after I figure out this icon problem.

Community
  • 1
  • 1
ChrisWilson4
  • 195
  • 4
  • 23
  • 1) The most relevant code is in your ButtonListener class I think. Why haven't you posted this? 2) Also what debugging have you done? Are you able to show any images at all? – Hovercraft Full Of Eels Jan 20 '14 at 23:14
  • You know if you run into problems like this, you should try to solve them first in small tester programs, not in your assignment. I'd first make sure to create a very small program that displays an ImageIcon in a JOptionPane and nothing more. – Hovercraft Full Of Eels Jan 20 '14 at 23:15
  • Also, You should provide an image of your package structure, and where your images reside in relationship to this structure. This is key. If not an image, there are jar commands that will give us pretty much the same thing (if the program is in a jar). – Hovercraft Full Of Eels Jan 20 '14 at 23:16
  • Again, where are the images relative to your class structure? – Hovercraft Full Of Eels Jan 20 '14 at 23:19
  • 1
    This is working absolutely perfectly for me, are you sure the images are where they should be? – Octal Software Jan 20 '14 at 23:21
  • The gifs are in the src and the bin. I put them in the bin just in case that would help, even though I don't know why it would. – ChrisWilson4 Jan 20 '14 at 23:21
  • C:\Users\BigBoy\workspace_1\EventDriven\src.x.gif – ChrisWilson4 Jan 20 '14 at 23:22
  • 1
    *"I already checked this duplicate question and it didn't help."* I can't understand why you did not notice that the duplicate question has an answer which is attempting to load the images by URL, whereas your code is trying to load them as if they were a `File`. For this type of [tag:embedded-resource], the icons *will not be available as a `File`!* – Andrew Thompson Jan 21 '14 at 00:22
  • I copied the wrong link, had a lot of tabs open with similar content. – ChrisWilson4 Jan 21 '14 at 00:35

1 Answers1

4

You need to understand resources which is what you will want to use. They are located relative to the class files. If the images are with the class files, then

  • get your image as a resource
  • Create an ImageIcon from the Image.

i.e., something like:

package whateverpackeyouareusing;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;


public class DefaultFoo {
   public static void main(String[] args) throws IOException {
      String resource = "x.png";
      URL url = Class.class.getResource(resource);
      BufferedImage img = ImageIO.read(url);
      Icon icon = new ImageIcon(img);
      JOptionPane.showMessageDialog(null, icon);
   }
}

Edit: A better example per Andrew Thompson:

package some.package;

import java.awt.Image;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;


public class PlayWithImages {
   public static final String X_RESOURCE = "x.png";
   private Icon xIcon;

   public PlayWithImages() throws IOException {
      URL xImgUrl = getClass().getResource(X_RESOURCE);
      Image xImg = ImageIO.read(xImgUrl);
      xIcon = new ImageIcon(xImg);
   }

   public Icon getXIcon() {
      return xIcon;
   }

   public static void main(String[] args) {
      try {
         PlayWithImages playWithImages = new PlayWithImages();
         Icon xIcon = playWithImages.getXIcon();
         JOptionPane.showMessageDialog(null, xIcon);
      } catch (IOException e) {
         e.printStackTrace();
      }

   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • `URL url = Class.class.getResource(resource);` **AFAIR** the class loader we can get in a `static` method like `main` is not the context class loader. Only the context class loader will have the `x.png` on the class-path. For that reason I always try to load resources in a non-static method and then use `this.getClass().getResource(..)` for loading application resources.. – Andrew Thompson Jan 21 '14 at 00:08
  • Yes. That 2nd one is how I'd approach it. :) – Andrew Thompson Jan 21 '14 at 00:20
  • OK, I'm so irritated. I made a smaller test program with just a single button and tried setting the Icon on it. Didn't work in Eclipse but worked fine in JGrasp. Tried my original program in JGrasp and it works! Turns out the GIFs need to be in the Package folder, not the SRC or the BIN folder. So in my case I had to drop the GIFs in C:\Users\BigBoy\workspace_1\EventDriven – ChrisWilson4 Jan 21 '14 at 00:45
  • Your answer seems a little above my head, using URLs. I'm sure it's a good answer, but all I needed to do was put my image files in the Project folder. – ChrisWilson4 Jan 21 '14 at 00:47
  • @ChrisWilson4: what you've done is made your code unusable for when you put it into a Jar. Play with resources and learn to use them or risk the consequences. – Hovercraft Full Of Eels Jan 21 '14 at 00:50