2017-03-27 44 views
0

我对放置在框架上的一个标签,一个简单的Swing程序之前出现,睡眠一秒钟,然后放置另一个标签的框架如下:JLabel的不眠

import javax.swing.*; 
import java.util.concurrent.*; 
public class SubmitLabelManipulationTask { 
    public static void main(String[] args) throws Exception { 
    JFrame frame = new JFrame("Hello Swing"); 
    final JLabel label = new JLabel("A Label"); 
    frame.add(label); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(300, 100); 
    frame.setVisible(true); 
    TimeUnit.SECONDS.sleep(1); 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     label.setText("Hey! This is Different!"); 
     } 
    }); 
    } 
} 

然而,在睡眠之前我看不到屏幕上的第一个标签。睡觉时屏幕空白。之后,我看到了原来的标签,然后立即看到最后的标签“嘿!这是不同的!”在屏幕上。为什么原始标签不出现在JFrame上?

+4

您需要使用摆动计时器 – AMB

+1

@AMB:不需要重新验证或重画,因为他不添加或删除组件。 OP,所有你需要的是一个Swing Timer来代替你的睡眠代码,因为睡眠的调用是在事件线程上完成的,它将整个GUI都置于睡眠状态 - 而不是你想要的。 –

+0

@DontKnowMuchButGettingBetter多数民众赞成我想说,TY – AMB

回答

1

这是更好的,更安全的替代你的睡眠代码中使用Swing定时器,因为调用睡觉事件线程上正在做的风险,这可以把整个GUI睡觉 - 不是你想要的。您还需要注意确保您的GUI实际上是在Swing事件线程上启动的。例如

import javax.swing.*; 
import java.util.concurrent.*; 

public class SubmitLabelManipulationTask { 
    public static void main(String[] args) throws Exception { 
     SwingUtilities.invokeLater(() -> { 
      JFrame frame = new JFrame("Hello Swing"); 
      final JLabel label = new JLabel("A Label", SwingConstants.CENTER); 
      frame.add(label); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.setSize(300, 100); 
      frame.setVisible(true); 
      Timer timer = new Timer(1000, e -> { 
       label.setText("Try this instead"); 
      }); 
      timer.setRepeats(false); 
      timer.start(); 
     }); 
    } 
} 
+2

'因为睡眠的调用正在事件线程上完成“ - main()方法中的代码不在EDT上执行。这就是为什么在创建GUI时,您需要将代码包装在SwingUtilities.invokeLater()中以将代码放在EDT上。也许sleep()方法在EDT上自动执行,但我不这么认为,因为在API中没有提到这一点。 – camickr

+0

“所有你需要的是一个摆动计时器”是不正确的 - 问题是不知何故'main'正在EDT上执行。给定的代码对我来说工作正常,也许OP使用一些执行EDT上的'main'的IDE。无论如何,正确的方法是像上面那样使用'invokeLater'来创建并显示JFrame。 –

+0

@CarlosHeuberger:好点。由于它创建并显示了一个Swing GUI,因此代码**实际上应该在EDT上被调用。所以最佳做法推荐我所建议的内容。 –

0

通过你的工作没有我的机器上的任何问题,完全没有写入的代码..

import javax.swing.*; 
import java.util.concurrent.*; 
public class SubmitLabelManipulationTask { 
    public static void main(String[] args) throws Exception { 
    JFrame frame = new JFrame("Hello Swing"); 
    final JLabel label = new JLabel("A Label"); 
    frame.add(label); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(300, 100); 
    frame.setVisible(true); 
    TimeUnit.SECONDS.sleep(1); 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     label.setText("Hey! This is Different!"); 
     } 
    }); 
    } 
} 
+0

如果原始海报**正确地**在Swing事件线程上创建并显示他的Swing GUI,会发生什么情况 - 您的代码是否仍然按照需要运行?换句话说,如果主方法中的所有代码都包装在Runnable中,然后通过'SwingUtilities.invokeLater(...)'在Swing事件线程上排队,会发生什么情况,如前面的答案所示?再说一次,在这种情况下,你的代码能否像预期的那样工作?如果不是,为什么要提出原始海报遵循错误设计的建议? –

+0

@HovercraftFullOfEels ..同意你的观点,我不会按要求工作..我只是尝试了原始代码张贴和它为我工作...感谢纠正我。,删除我的建议.. :) –

0

马特的评论,虽然GUI正在加载固定的问题对我来说,睡眠是发生。结果发现尽管JFrame立即加载,但加载其他组件需要大约一秒钟的时间。因此,当标签正确完成时,随后会完成睡眠并且标签几乎立即被切换。将睡眠(或定时器)改变超过一秒钟,可让我在切换前看到原始标签一段时间。

+0

仍然,你的代码不正确 - 您应该在事件线程上创建并显示GUI,然后使用Swing Timer,如针对您的问题的第一个回答中所演示的。按照这个建议,接受这个答案,因为它是最正确的。 –