2016-05-18 3 views
0

私は、接続されたUSBデバイスへの接続を開始する完全なGUIを持っています。スタートアップの手順は約3秒かかります。その間、私はプログラムが開始していることをユーザーに知らせるスプラッシュ画面を表示したい。私は "SplashFrame"クラス(JFrameの拡張)を作成し、2つのラベルを持つパネルを作成し、フレームに貼り付けました。新しいものを開く前にJFrameを完全にロードする

しかし、SplashFrameは、他の「メイン」フレームのセットアップ手順が完了した時点でのみ、完全にロードされるという問題があります。これは、意図的にSplashFrameを閉じる前に、どちらのラベルも読み込めないことを意味します。メインフレームを起動する前にSplashFrameを完全にロードするにはどうすればよいですか?

これは私のメインの方法

private static JFrame frame; 
private static SplashFrame splash; 

public static void main(String[] args){ 

    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      // Turn off metal's use of bold fonts 
      UIManager.put("swing.boldMetal", Boolean.FALSE); 

      splash = new SplashFrame(); 
      long startTime = System.currentTimeMillis(); 
      frame = new CFSMainFrame(); 
      long endTime = System.currentTimeMillis(); 
      long totalTime = endTime - startTime; 
      System.out.println("Total time: " + ((float)totalTime/1000) + " seconds!"); 
      splash.closeFrame(); 
     } 
    }); 
} 

であり、これは私がやってみました(私は自分自身を日食使用しています)はNetbeansを使用してチュートリアルの膨大な量を見た後、私のsplashFrame

public class SplashFrame extends JFrame{ 

private static JFrame frame; 

public SplashFrame(){ 
    frame = new JFrame("Loading..."); 
    frame.setLayout(new BorderLayout()); 
    frame.setSize(300, 150); 

    ImageIcon img = new ImageIcon("resources/mini_logo.png"); 
    frame.setIconImage(img.getImage()); 

    JPanel pane = splashPanel(); 
    frame.add(pane); 
    createAndShowGUI(); 
} 

private JPanel splashPanel(){ 
    JPanel pane = new JPanel(new BorderLayout()); 

    ImageIcon loadingImg = new ImageIcon("resources/logo.png"); 
    JLabel imageLabel = new JLabel(); 
    imageLabel.setIcon(loadingImg); 

    JLabel loadingLabel = new JLabel("Loading"); 

    loadingLabel.setHorizontalAlignment(SwingConstants.CENTER); 
    loadingLabel.setVerticalAlignment(SwingConstants.CENTER); 
    loadingLabel.setPreferredSize(new Dimension(150, 165)); 

    pane.add(imageLabel, BorderLayout.CENTER); 
    pane.add(loadingLabel, BorderLayout.PAGE_END); 

    return pane; 
} 

private void createAndShowGUI(){ 
    frame.pack(); 
    frame.setVisible(true); 
    frame.setResizable(false); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setLocationRelativeTo(null); 
} 

public void closeFrame(){ 
    frame.setVisible(false); 
    frame.dispose(); 
} 
+1

[オラクルチュートリアル:どのようにスプラッシュ画面を作成する](https://docs.oracle.com/javase/tutorial/uiswing/misc/splashscreen.html )。 –

答えて

0

です私のコードとは別のものがいくつかあります。私が気づいたことの1つは、すべてのチュートリアルで、「スプラッシュ」デモがスレッドを通して実行されていないことでした。だから私はスプラッシュフレームの初期化をスレッドから外してみました。そして、そのトリックをしました。

private static JFrame frame; 
private static SplashFrame splash; 

public static void main(String[] args) throws IOException { 

    UIManager.put("swing.boldMetal", Boolean.FALSE); 
    splash = new SplashFrame(); 

    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       Thread.sleep(4500); //Extending time to show the splash screen 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      long startTime = System.currentTimeMillis(); 
      frame = new CFSMainFrame(); 
      long endTime = System.currentTimeMillis(); 
      long totalTime = endTime - startTime; 
      System.out.println("Total time: " + ((float)totalTime/1000) + " seconds!"); 
      splash.closeFrame(); 

     } 
    }); 
} 

は、まず私は、しかし、これは動作しませんでした、メインフレームの初期化前にsplash.closeFrame()メソッドを持っていました。私は、コード "タイミング"コードがセットアップ時間を報告し、closeFrame()メソッド呼び出しをそこに置くことに気付き、意図したとおりに機能しました。

EDIT

私はこれを行うことは、インターフェイスが静止したまま、それはインターフェースまたは同様のものを更新するためのスレッドを実行していないため、変更することができないことがわかりました。私はスプラッシュフレームに回転ローディングアイコンを示すgifイメージを置いて、非常に適切ではないようにしたかったのです。

は、だから私はこれにアプローチを変えてしまった:

public static void main(String[] args) throws IOException { 

    UIManager.put("swing.boldMetal", Boolean.FALSE); 

    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      splash = new SplashFrame(); 

      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        long startTime = System.currentTimeMillis(); 
        frame = new CFSMainFrame(); 
        long endTime = System.currentTimeMillis(); 
        long totalTime = endTime - startTime; 
        System.out.println("Total time: " + ((float)totalTime/1000) + " seconds!"); 
        splash.closeFrame(); 
       } 
      }); 
     } 
    }); 
} 

私は、これはこれを達成する最良の最適化された方法であるとは言わないよ、それは私が必要/たかった結果が得られました。

1

あなたのUIからUSB接続ロジックを分離することをお勧めします。これにより、論理フローのスプラッシュスクリーンにメインスレッドを使用し、USB経由で接続を開始し、接続されている場合はアプリケーション画面を表示することができます。 それはのように見えることができるものだけでラフ例:

public static void main(String[] args) { 
    final SplashFrame splash = new SplashFrame(); 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      splash.pack(); 
      splash.setVisible(true); 
     } 
    }); 

    USBConnection usbConnection = new USBConnection(); 
    boolean success = usbConnection.connect(); 
    if(!success){ 
     System.err.println("Could not connect to USB device."); 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       splash.setVisible(false); 
       splash.dispose(); 
      } 
     }); 
     return; 
    } 

    final CFSMainFrame application = new CFSMainFrame(usbConnection); 

    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      splash.setVisible(false); 
      splash.dispose(); 
      application.pack(); 
      application.setVisible(true); 
     } 
    }); 
} 
+0

これはすばらしいアイデアであり、おそらく望ましい結果を達成する最適な最適な方法です。しかし、USB接続を設定すると結果が返ってくるデバイスでいくつかのテストが実行され、これらの結果がメインフレームの外観を決めるために使用されるため、これに関する懸念が1つあります。それが問題かもしれないと思いますか? – Zeliax

+1

初期化中に何をしても、結果はUSBConnectionインスタンスの属性として保存できます。構築中にCFSMainFrameへの参照として渡すので、必要な情報を取得できます。 – Alexander

+0

オハイオ州。私はその部分を逃した。私はそれを実装し、それは動作しているようだが、私は、ソースを見つける必要があるNullPointerException小さな問題がありますが、私は確かに答えとしてあなたの答えを追加する問題を解決する。ありがとう!:P – Zeliax

関連する問題