2016-11-02 33 views
1

以下のコードは、私がEclipseで開発した小さなJavaアプリケーション用のスプラッシュ画面の実装です。スプラッシュスクリーンはPC上ではうまく動作しますが、MACでは動作しません。 MAC OSXでは、フレームが最初に表示され、2秒間にグレーの領域が表示され、残りの4秒間に画像が表示されます。通常、画像は直ちに4秒間表示されます。 MAC上に画像が表示されるまでに時間がかかり、PC上ですべてうまく動作する理由は何ですか? PS:実行可能な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

編集これは、元の答えは全く異なります。私は下の元の答えを残しています。

OSXで最初のJLabelレンダリングが遅くなっているようです。すべてのスリープを解除すると、Javaがラベルをレンダリングしている間に2秒間の一時停止が残っています。だから我々はルールを変更する。

まず、我々はバッファリングされたイメージとるのJPanelクラスを作成:私たちはそのようにのようなスプラッシュ画面のコンストラクタを変更

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); 
} 

これは、すぐにパネルが表示されている画像をレンダリング休止せずに。

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スレッドオフ睡眠を置くことの簡単な例、[OK]を - このコードは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の「完了」部分にコールを入れる必要があります。これは、SwingWorkerをメインクラスに移動してスプラッシュ画面とメインウィンドウの両方を参照することで比較的簡単に処理できます。一方のオープンを制御し、他方のクローズを制御することを可能にする。 – Petesh

+0

私はSwingWorkerクラスを実装しました。それはMac OSX上では問題を解決しませんでした(ただし、PC上で動作します)。 Jarファイルをダブルクリックして約2秒間灰色のウィンドウが残っていれば、残りの4分間のThread.Sleep()の画像が表示されます。ですから、問題は私がUIスレッドをブロックしているということではありません(すべてのソリューションはPC上で動作します)。 Mac OSXでは動作しません。別のアイデアがある場合は、メッセージを投稿してください!ありがとうございました! – user3787028

+0

初期灰色のウィンドウは、JVMがJLabelでイメージをレンダリングする間です。この場合、スレッドスリープとは特に関係ありません。 jpanelのような軽いものを使うように答えを変えてみましょう。 – Petesh

関連する問題