2017-03-27 47 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,如針對您的問題的第一個回答中所演示的。按照這個建議,接受這個答案,因爲它是最正確的。 –