【问题标题】:Thread.sleep (change image) JavaThread.sleep(更改图像)Java
【发布时间】:2012-11-29 04:52:53
【问题描述】:

我有两个带有图像的jlabels..我尝试在单击另一个标签时更改标签中的图像..(例如游戏).. 我有一个问题..当我写 Thread.sleep 图像没有改变..见代码:

public class Game extends JFrame{
private JLabel l1,l2;;
private boolean isClicked = false ,isClicked2 = false;
public Game(){
    setLayout(new FlowLayout());
    l1 = new JLabel(new ImageIcon(getClass().getResource("image1.png")));
    add(l1);
    l2 = new JLabel(new ImageIcon(getClass().getResource("image1.png")));
    add(l2);


    l1.addMouseListener(new MouseListener() {
        @Override
        public void mouseClicked(MouseEvent e) {}
        @Override
        public void mousePressed(MouseEvent e) {}
        @Override
        public void mouseReleased(MouseEvent e) {
            if(isClicked2){
                l1.setIcon(new ImageIcon(getClass().getResource("image2.png")));
                try {
                    Thread.sleep(1000);
                    l1.setIcon(new ImageIcon(getClass().getResource("image1.png")));
                    l2.setIcon(new ImageIcon(getClass().getResource("image1.png")));
                    isClicked2 = false;
                    isClicked = false;
            }catch(InterruptedException ex){}
            }
            else{
                l1.setIcon(new ImageIcon(getClass().getResource("image2.png")));
                isClicked = true;
            }     
        }@Override public void mouseEntered(MouseEvent e){}@Override public void mouseExited(MouseEvent e){}
    });

    l2.addMouseListener(new MouseListener() {
        @Override
        public void mouseClicked(MouseEvent e) {}
        @Override
        public void mousePressed(MouseEvent e) {}
        @Override
        public void mouseReleased(MouseEvent e) {
            if(isClicked){
              try {
                    l2.setIcon(new ImageIcon(getClass().getResource("image2.png")));
                    Thread.sleep(1000);
                    l2.setIcon(new ImageIcon(getClass().getResource("image1.png")));
                    l1.setIcon(new ImageIcon(getClass().getResource("image1.png")));
                isClicked = false;
                    isClicked2 = false;
              }catch(InterruptedException ex){}  
            }
            else{
                l2.setIcon(new ImageIcon(getClass().getResource("image2.png")));
                isClicked2 = true;
            }     
        }@Override public void mouseEntered(MouseEvent e){}@Override public void mouseExited(MouseEvent e){}
    });
}

public static void main(String[] args) {
    Game g = new Game();
    g.setTitle("Fint the same");
    g.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    g.pack();
    g.setVisible(true);
}

}

运行它并首先单击第一个标签。单击第二个标签后,第一个标签将在 1 秒内更改图像,但 seconf 标签永远不会!!

【问题讨论】:

  • 您确实意识到在第一个听众中您有Thread.Sleep(1000),而在第二个听众中您有Thread.CurrentThread.Sleep(1000),对吗?不知道这是否会有所不同,但这有点吓到我了。
  • Thread.sleep() 是一个静态方法,在 Thread 对象(currentThread)上调用它不会改变任何东西,它会一直在当前线程上休眠。
  • Yes..no .CurrentThread... 但是同样的问题.. koljaTM:我能做什么?

标签: thread-sleep


【解决方案1】:

图像的更改必须在事件线程(用于处理图形事件的线程)上完成。因此,设置图像将在您的方法返回后将要处理的适当事件排队。不过,那时图像已经变回了,因为事件线程上的 sleep() 不允许处理任何其他事件。 正如 dashrb 所说,不要 sleep() 主线程,而是在 Timer 中安排翻转:

                if (isClicked) {

                    l2.setIcon(new ImageIcon(getClass().getResource("image2.png")));

                    new javax.swing.Timer(1000, new ActionListener() {
                        @Override
                        public void actionPerformed(final ActionEvent e) {
                            l2.setIcon(new ImageIcon(getClass().getResource("image1.png")));
                            l1.setIcon(new ImageIcon(getClass().getResource("image1.png")));
                            isClicked = false;
                            isClicked2 = false;
                        }
                    }).start();

                } catch (final Exception ex) {
                    ex.printStackTrace();
                }
            } else {
               ...

【讨论】:

  • 好的,谢谢..我理解这个问题,但我不知道如何在计时器中翻转..如果能够帮助我将非常有用
  • 非常感谢!!但是 1 个问题:类 Timer 中的构造函数 Timer 不能应用于给定类型;必需:int,找到ActionListener:无参数原因:实际参数列表和正式参数列表的长度不同
  • 这是一个简短的教程:how to use swing timers
  • 我相信上面的示例代码是基于 java.util.Timer 的(因为显示了一个无参数的构造函数)。 UTIL 定时器在任意线程中执行;相反,SWING 计时器在事件调度线程上执行,这对于更改摇摆 JLabels 上的图像是必需的! SWING Timer 教程链接在我之前的评论中,你的代码看起来像:timer = new javax.swing.Timer(1000, this);。您将在您的类中定义一个public void actionPerformed(ActionEvent e) 方法,而不是如上所示的run() 方法。
  • 我想我相应地修改了这个答案。 交叉手指
【解决方案2】:

您不应该在这些方法中使用 sleep() —— 它们是从处理所有绘图事件的“事件调度”线程调用的。如果您正在睡觉,那么线程无法重新绘制您的标签。

与其休眠,不如更改您的图像,然后创建一个 javax.swing.Timer 任务,该任务将在 1 秒后触发以根据需要再次更改图像。上面的 koljaTM 示例使用了 java.util.Timer,它在“错误”线程中运行。这是他的代码,修改为使用 SWING 计时器:

            if (isClicked) {
            try {
                l2.setIcon(new ImageIcon(getClass().getResource("image2.png")));
                javax.swing.Timer timer = new javax.swing.Timer(1000, new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        l2.setIcon(new ImageIcon(getClass().getResource("image1.png")));
                        System.out.println("image2 gone");
                        l1.setIcon(new ImageIcon(getClass().getResource("image1.png")));
                        isClicked = false;
                        isClicked2 = false;
                    }
                });
                timer.setRepeats(false);
                timer.start();
            } catch (final Exception ex) {
                ex.printStackTrace();
            }
        } else {
           ...

【讨论】:

  • 而不是 Thread.sleep() 我能做什么?感谢您的回复!
  • 我修改了答案以包含示例代码(受上面的 koljaTM 启发)。我希望它有所帮助。
  • 现在它运行没有编译错误,但不幸的是它有同样的问题。不过,非常感谢你
  • 你可能需要更多的 println() 来准确地确定什么被调用,什么不是。这些按钮看起来应该具有相同的行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-14
  • 2012-04-28
  • 2013-06-06
  • 2020-07-15
  • 1970-01-01
相关资源
最近更新 更多