0

I am making a little farm game demo of changing seed to a plant using JLabel, the seed image is initialized after bt1 is clicked, then I used thread to make the label image changed to a grown plant after few seconds time. But I'm having this problem that the seed image is never appearing. Is that because I called run method so the main thread is interrupted by thread time? What should I alter to make the see.jpg show up on JLabel before wheat.jpg taking over it? Here is my code.

public class UI {
    JButton bt1, bt2, bt3, bt4, bt5, bt6;
    JPanel gamePanel;

    public UI(){
        JFrame frame = new JFrame("Little Farm Game");
        JPanel mainPanel = new JPanel(new GridLayout(2,5));
        gamePanel = new JPanel(new GridLayout(3,4));
        JPanel controlPanel = new JPanel(new GridLayout(3,3));
        controlPanel.setBackground(Color.DARK_GRAY);

        bt1 = new JButton("Wheat Seed");
        bt2 = new JButton("Flower Seed");
        bt3 = new JButton("Land Purchase");
        bt4 = new JButton("Wheat Seed Purchase");
        bt5 = new JButton("Flower Seed Purchase");
        bt6 = new JButton("Wallet: "+ Wallet.getInstance().getCurrentMoney());

        Thread time = new Thread(){

            @Override
            public void run() {
                try {       
                    sleep(300);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                for(int i=0; i<gamePanel.getComponentCount(); i++)
                {
                    JLabel label = (JLabel) gamePanel.getComponent(i);
                    label.setIcon(new ImageIcon(getImage("src/wheat.jpg")));
                }
            }
        };

        bt1.addActionListener(new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub

             gamePanel.add(new JLabel(new ImageIcon(getImage("src/flowerseed.jpg"))));
             gamePanel.validate();

               time.run();
            }
        });

        controlPanel.add(bt1);
        controlPanel.add(bt2);
        controlPanel.add(bt3);
        controlPanel.add(bt4);
        controlPanel.add(bt5);
        controlPanel.add(bt6);
        mainPanel.add(gamePanel);
        mainPanel.add(controlPanel);
        frame.add(mainPanel);
        frame.setSize(600, 400);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
    }

    public static Image getImage(final String pathAndFileName) {

        return Toolkit.getDefaultToolkit().getImage(pathAndFileName);
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Zoe
  • 49
  • 4
  • 1
    We can only guess what you might be doing wrong, and mine would be that you're not truly using a background thread correctly, but your little snippet of code is not enough for us to know for sure. Best if you create and post a [minimal example program](http://stackoverflow.com/help/mcve). – Hovercraft Full Of Eels Mar 07 '15 at 16:52
  • 1
    BTW - rather than trying to add the label to the GUI on button click, add it at start-up with no text or icon. It will be invisible until the icon is set. Oh, and one way to get image(s) for the example mentioned by @HovercraftFullOfEels is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). – Andrew Thompson Mar 07 '15 at 16:55
  • *"Here is my code."* An uncompilable code snippet is not an MCVE. *"Typing on phone so bad format sorry!"* Rather than (pointless) apologies, you should wait till you are at a machine where you you can follow links, read articles, and comply with the advice in them. – Andrew Thompson Mar 07 '15 at 17:00
  • Sorry I live in china and my VPN only works on mobile device which is weird, I want to use PC to ask too, anyway tried my best to have them altered. – Zoe Mar 07 '15 at 17:04
  • 1
    @AndrewThompson: thanks again for the images link! Used them in my answer code! – Hovercraft Full Of Eels Mar 07 '15 at 17:09
  • 1
    @HovercraftFullOfEels Gee.. now you made me want to up-vote again! – Andrew Thompson Mar 07 '15 at 17:11

1 Answers1

3
  1. Don't directly use Threads for this. There's no need, and it carries risk if you call code in a background thread that changes Swing state without care, which is exactly what you're doing.
  2. Use a Swing Timer for your animation loop.
  3. Display your images as ImageIcons in a JLabel.
  4. As mentioned, have the JLabel in your GUI from the get go.
  5. Read in your image Icon just once, and save it in a variable or collection.
  6. You can easily pause a Swing Timer by simply calling its stop() method, and can restart it just as easily by calling start().
  7. For your benefit and ours, learn and use good Java formatting, especially when posting code on this site. Your current code is all left-justified, making the code difficult to read and understand.

For example, and using Andrew's images:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.*;

public class ChangingImages extends JPanel {
   public static final String SPRITE_SHEET_PATH = "https://i.stack.imgur.com/SeZ5y.png";
   private static final int DELAY = 400;
   private List<Icon> imageIconList = new ArrayList<>();
   private JLabel label = new JLabel();

   public ChangingImages() throws IOException {
      URL imgUrl = new URL(SPRITE_SHEET_PATH);
      BufferedImage img = ImageIO.read(imgUrl); 
      for (int i = 0; i < 2; i++) {
         for (int j = 0; j < 6; j++) {
            int x = (img.getWidth() * j) / 6;
            int y = (img.getHeight() * i) / 2;
            int w = img.getWidth() / 6;
            int h = img.getHeight() / 2;
            BufferedImage subImg = img.getSubimage(x, y, w, h);
            imageIconList.add(new ImageIcon(subImg));            
         }
      }

      add(label);
      label.setIcon(imageIconList.get(0));

      new Timer(DELAY, new ActionListener() {
         int index = 0;
         @Override
         public void actionPerformed(ActionEvent e) {
            index++;
            index %= imageIconList.size();
            label.setIcon(imageIconList.get(index));
         }
      }).start();
   }

   private static void createAndShowGui() {
      ChangingImages mainPanel = null;
      try {
         mainPanel = new ChangingImages();
      } catch (IOException e) {
         e.printStackTrace();
         System.exit(-1);
      }

      JFrame frame = new JFrame("ChangingImages");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373