【问题标题】:Main thread being interrupted by another thread after run method is called?调用run方法后主线程被另一个线程中断?
【发布时间】:2015-03-07 16:51:26
【问题描述】:

我正在制作一个使用 JLabel 将种子更改为植物的农场小游戏演示,单击 bt1 后初始化种子图像,然后我使用线程将标签图像在几秒钟后更改为生长的植物。但是我遇到了种子图像永远不会出现的问题。 那是因为我调用了 run 方法所以主线程被线程时间中断了吗?在wheat.jpg接管它之前,我应该改变什么以使see.jpg出现在JLabel上?这是我的代码。

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);
    }
}

【问题讨论】:

  • 我们只能猜测您可能做错了什么,而我的可能是您并没有真正正确使用后台线程,但是您的小sn-p代码不足以让我们知道当然。最好创建并发布minimal example program
  • 顺便说一句 - 与其尝试在按钮单击时将标签添加到 GUI,不如在启动时添加它,不带文本或图标。在设置图标之前它将是不可见的。哦,为@HovercraftFullOfEels 提到的示例获取图像的一种方法是热链接到this Q&A 中看到的图像。
  • “这是我的代码。” 不可编译的代码 sn-p 不是 MCVE。 “在手机上打字太糟糕了,抱歉!” 与其(毫无意义的)道歉,不如等到你来到一台可以点击链接、阅读文章并遵守其中建议的机器前.
  • @AndrewThompson:再次感谢图片链接!在我的答案代码中使用它们!
  • @HovercraftFullOfEels Gee.. 现在你让我想再次投票!

标签: java multithreading swing


【解决方案1】:
  1. 不要为此直接使用线程。没有必要,而且如果您在后台线程中调用代码会不小心更改 Swing 状态,这会带来风险,这正是您正在做的事情
  2. 在动画循环中使用 Swing Timer。
  3. 在 JLabel 中将图像显示为 ImageIcons。
  4. 如前所述,从一开始就在您的 GUI 中使用 JLabel。
  5. 只需读取一次图像图标,并将其保存在变量或集合中。
  6. 您可以通过调用stop() 方法轻松暂停Swing Timer,也可以通过调用start() 轻松重启它。
  7. 为了您和我们的利益,学习和使用良好的 Java 格式,尤其是在本网站上发布代码时。您当前的代码都是左对齐的,导致代码难以阅读和理解。

例如,使用 Andrew 的图片:

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 = "http://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();
         }
      });
   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多