【问题标题】:No delay in GUI execution even after implementing sleep in a separate thread即使在单独的线程中实现睡眠后,GUI 执行也不会延迟
【发布时间】:2014-09-24 21:27:53
【问题描述】:

我正在编写一个代码来移动特定数量的形状。我已将此代码放在一个循环中,以便程序移动形状 10 次。但是,不仅仅是显示最后的输出,我还想看到形状移动。所以,我在一个单独的线程中实现了 sleep 方法。但是,形状仍然快速移动,我只看到最终输出。

有人知道这里的问题是什么,我该如何解决?

代码:

public void actionPerformed(ActionEvent e)
{
    if (e.getActionCommand().equals("START"))
    {
            for(int i=0;i<100;i++)
            {
                pf.particleFilter();
                repaint();  
                sleepFunction();
            }

    }   
}

private void sleepFunction()
{
    System.out.println("In sleep thread");
    Thread mythread = new Thread()
    {
        public void run()
        {
            try
            {
                System.out.println("Going to sleep!");
                Thread.sleep(1000);
            }
            catch(InterruptedException ex)
            {
                Thread.currentThread().interrupt(); 
            }   
        }

    };
    mythread.start();
}

public void particleFilter()
    {
            move();     
    }   

    public void move()
    {
        setXPosition_robot(robot_x);
        setYPosition_robot(robot_y);
        setXPosition_particle(particle_x);
        setYPosition_particle(particle_y);
    }

【问题讨论】:

  • 你正在创建一个新线程,让它休眠一秒钟,然后线程结束。这不会以任何方式与 GUI 线程交互。您可能有兴趣了解Swing Timers
  • @DSquare 所以,我应该删除线程并在 repaint() 之后使用一个计时器,例如 Timer timer = new Timer(1000, this); timer.setInitialDelay(1); timer.start();

标签: java multithreading swing


【解决方案1】:

睡眠函数在单独的线程中执行,因此它不会导致Event Dispatch Thread (EDT) 进入睡眠状态,因此 EDT 会继续执行。

这是一件好事,因为您永远不希望 EDT 休眠,因为这会阻止 GUI 重新绘制自身。

要制作动画,您需要使用Swing Timer。阅读 How to Use Swing Timers 上的 Swing 教程中的部分以获取更多信息。

我觉得教程中的例子有点复杂,所以这是我能想到的最基本的例子:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class TimerTime extends JPanel implements ActionListener
{
    private JLabel timeLabel;

    public TimerTime()
    {
        timeLabel = new JLabel( new Date().toString() );
        add( timeLabel );

        Timer timer = new Timer(1000, this);
        timer.setInitialDelay(1);
        timer.start();
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        timeLabel.setText( new Date().toString() );
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("TimerTime");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new TimerTime() );
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

【讨论】:

  • 那么,我应该删除我的线程并在 repaint() 之后的 actionPerformed 中添加一个计时器吗?
  • 不,您应该在计时器的侦听器中调用repaint(),以获取example
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-03
  • 2012-04-02
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
  • 2017-07-16
相关资源
最近更新 更多