2016-11-02 4 views
1

아래 코드는 Eclipse로 개발 한 작은 Java 응용 프로그램 용 스플래시 화면 구현입니다. 스플래시 화면은 PC에서는 완벽하게 작동하지만 MAC에서는 제대로 작동하지 않습니다. MAC OSX에서 프레임이 처음 나타나는 것은 2 초 동안 회색 영역이 나타나고 나머지 4 초 동안 이미지가 나타납니다. 이미지는 일반적으로 곧바로 4 초 동안 나타납니다. PC에서 모든 것이 잘 작동하는 동안 MAC에 이미지가 나타나기까지 지연되는 이유는 무엇입니까? 추신 : 실행 가능한 Jar로 응용 프로그램을 배포했으며 모든 컴퓨터에서 Java 8을 사용하고 있습니다. 고맙습니다.Mac OSX에서는 Java 스플래시 화면이 작동하지 않지만 PC에서는 작동 중임

public static void main(String[] args) 
{ 
    SplashScreen splSplashScreen = new SplashScreen(); 
    //Main window 
    FenetrePrincipale fenetrePrincipale = new FenetrePrincipale(); 
} 
public class SplashScreen extends JWindow 
{ 
    /** 
    * Numéro de série 
    */ 
    private static final long serialVersionUID = 1592663893301307318L; 

    private final static long TEMP_AFFICHAGE = 4000; 

    /** 
    * Constructeur par initialisation 
    * @param p_Frame Frame 
    * @param p_TempsAffichage Temps d'affichage en millisecondes 
    */ 
    public SplashScreen() 
    { 
     super(new Frame()); 
     JLabel lblImage = new JLabel(new ImageIcon(this.getClass().getResource("/res/ui/splashScreen.jpg"))); 

     Container container = this.getContentPane(); 
     container.add(lblImage, BorderLayout.CENTER); 
     pack(); 

     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
     Dimension labelSize = lblImage.getPreferredSize(); 
     this.setLocation(screenSize.width/2 - (labelSize.width/2), screenSize.height/2 - (labelSize.height/2)); 

     this.setVisible(true); 

     try 
     { 
      Thread.sleep(TEMP_AFFICHAGE); 
     } 
     catch (InterruptedException ex) 
     { 
      ApplicationLogger.getInstance().severe(ex.getLocalizedMessage()); 
     } 
     finally 
     { 
      this.setVisible(false); 
     } 
    } 
} 
+0

'Thread.sleep()'은 java 어플리케이션으로 하여금 메시지 처리를 멈추게합니다; 이는 UI가 업데이트되지 않는다는 것을 의미합니다. [이 답변] (http://stackoverflow.com/questions/16288303/best-example-for-programmatically-creating-splashscreen-with-text)에있는 미리보기를 따르면 작업자를 적절하게 작성하는 데 도움이됩니다. – Petesh

+0

그러나 이미지는 Thread.sleep() 끝 부분 앞에 나타납니다. Thread.sleep() (this.setVisible (true);) 전에 이미지가로드되기 때문에 Thread.sleep()이 이미지로드를 중지해서는 안됩니다. – user3787028

+0

문제를 일으키는 재 페인트를 중지합니다. UI 스레드를 차단하면 이러한 일이 발생합니다. 해결 방법은 * UI 스레드를 차단하지 않는 것입니다. * – Petesh

답변

2

편집이 원래의 대답은 완전히 다릅니다; 아래에 원래 답변을 남겨두고 있습니다.

초기 JLabel 렌더링이 OSX에서 개가 느린 것 같습니다. 모든 절전 모드를 제거하면 Java에서 레이블을 렌더링하는 동안 ~ 2 초의 일시 중지가 발생합니다. 그래서 우리는 규칙을 바꿉니다.

class ImgPanel extends JPanel { 
    private BufferedImage img; 

    public ImgPanel(BufferedImage img) { 
     this.img = img; 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(img.getWidth(), img.getHeight()); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(img, 0, 0, null); 
    } 
} 

우리는 다음과 같이 시작 화면 생성자를 변경 :

public SplashScreen() 
{ 
    BufferedImage img = null; 
    try { 
     img = ImageIO.read(this.getClass().getResource("/res/ui/splashScreen.jpg")); 
    } catch (Exception ex) { 
    } 

    ImgPanel panel = new ImgPanel(img); 
    Container container = this.getContentPane(); 
    container.add(panel); 
    pack(); 

    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
    this.setLocation(screenSize.width/2 - (img.getWidth()/2), screenSize.height/2 - (img.getHeight()/2)); 

    this.setVisible(true); 
} 

이 이미지를 렌더링하는 즉시 패널이 나타나는

먼저 우리는 버퍼 이미지를 소요 JPanel의 클래스를 생성 멈추지 않고.

class worker extends SwingWorker<String, Object> { 
    private final static long TEMP_AFFICHAGE = 4000; 
    private SplashScreen splash; 
    private FenetrePrincipale principale; 

    public worker(SplashScreen splash, FenetrePrincipale principale) { 
     this.splash = splash; 
     this.principale = principale; 
     this.splash.setVisible(true); 
    } 

    @Override 
    public String doInBackground() { 
     try 
     { 
      Thread.sleep(TEMP_AFFICHAGE); 
     } 
     catch (InterruptedException ex) 
     { 
      ApplicationLogger.getInstance().severe(ex.getLocalizedMessage()); 
     } 
     return ""; 
    } 

    @Override 
    protected void done() { 
     splash.setVisible(false); 
     principale.setVisible(true); 
    } 
}; 
:

주 - 시작 화면의 숨기기 메인 화면의 표시를 수행하는 논리가 더 나은 별도의 SwingWorker를 캡처 할 것 - 나는 혼란을 줄이기 위해 전체 수면 코드를 제거했습니다

는 다음의 주요 코드는 외모와 같은 :

public static void main(String[] args) 
{ 
    SplashScreen splSplashScreen = new SplashScreen(); 
    //Main window 
    FenetrePrincipale fenetrePrincipale = new FenetrePrincipale(); 
    worker w = new worker(splSplashScreen, fenetrePrincipale); 
    w.execute(); 
} 

원래 대답 -에 수면의 실을 꿰기 SwingWorker는 초기화 전에 실제 작업을 수행 할 수 있으므로 여전히 좋은 생각입니다.

확인, GUI를 스레드 떨어져 잠을 넣어 당신의 시작 코드를 사용하는 간단한 예 -이 코드는 this.setVisible(true) 다음에 오는, 그리고 마지막으로 시도 {} 잡기 {} 대신 {} 절 :

this.setVisible(true); 

    worker do_work = new worker(this); 
    do_work.execute(); 
} 

class worker extends SwingWorker<String, Object> { 
    private SplashScreen parent; 

    public worker(SplashScreen parent) { 
     this.parent = parent; 
    } 

    @Override 
    public String doInBackground() { 
     try 
     { 
      Thread.sleep(TEMP_AFFICHAGE); 
     } 
     catch (InterruptedException ex) 
     { 
      ApplicationLogger.getInstance().severe(ex.getLocalizedMessage()); 
     } 
     return ""; 
    } 

    @Override 
    protected void done() { 
     parent.setVisible(false); 
    } 
}; 

그냥 잠을자는 doWorkInBackground으로 작성한 SwingWorker를 만들고 일단 끝나면 스플래시 화면 인 부모 프레임을 닫습니다.

+0

작성된 것처럼, 스플래시 화면이 계속 보이는 동안 기본 창이 열릴 수 있습니다. 스플래시 화면이 사라질 때까지 메인 윈도우가 보이지 않게하려면 SwingWorker의 'done'부분에 콜을 넣어야합니다. SwingWorker를 메인 클래스로 옮겨서 스플래시 스크린과 메인 윈도우 모두에 대한 참조를 갖게함으로써 상대적으로 쉽게 처리 할 수 ​​있습니다. 하나의 열림과 다른 열림의 닫힘을 제어 할 수 있습니다. – Petesh

+0

당신의 SwingWorker 클래스를 구현했습니다. Mac OSX에서는 전혀 문제를 해결하지 못했습니다 (그러나 PC에서 작동 함). Jar 파일을 두 번 클릭하면 약 2 초 동안 여전히 회색 창이 나타나고 Thread.Sleep()의 4 초 동안 이미지가 나타납니다. 그래서 문제는 내가 UI 스레드를 차단하지 않는다는 것입니다 (결국 모든 솔루션은 PC에서 작동합니다). Mac OSX에서는 작동하지 않습니다. 다른 아이디어가 있다면 메시지를 게시하십시오! 고맙습니다! – user3787028

+0

초기 회색 창은 JVM이 JLabel에서 이미지를 렌더링하는 동안입니다. 이 경우 스레드 수면과 관련이 없습니다. 나는 jpanel처럼 가벼운 것을 사용하기 위해 나의 대답을 바꿀 것이다. – Petesh

관련 문제