2014-06-24 62 views
0

我想創建一個加載消息,在加載信息時將在屏幕上彈出。我將爲它調用initLoadingPanel()方法,以便JFrame可見。我的問題是如何關閉它?Java Swing實用程序

我的代碼如下。

public class DataMigration extends JFrame{ 

    private JFrame frmDataMigration; 

    private JFrame loader; 

private JButton btnProcess; 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        DataMigration window = new DataMigration(); 
        window.frmDataMigration.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public DataMigration() { 
     initialize(); 
    } 

    private void initialize() { 

     LoggerImp.startLog(CLASS_NAME, "initialize()"); 

     frmDataMigration = new JFrame(); 

btnProcess = new JButton("Load"); 
     btnProcess.setEnabled(false); 
     btnProcess.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 

      SwingWorker <CSV, CSV> worker = new SwingWorker<CSV, CSV>() { 

       @Override 
       protected CSV doInBackground() throws Exception { 
        return FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText()); 
       } 

       @Override 
       protected void done() { 
        try { 
         csv = doInBackground(); 
         generateTableList(csv.getCsvTitle(), stateController.getFieldNames()); 
        } catch (ExecutionException ex) { 
         ex.printStackTrace(); 
        } catch (Exception e){ 

        } 
        loader.dispose(); 
       } 

      }; 
      worker.execute(); 
     } 
     }); 
    frmDataMigration.getContentPane().add(btnProcess); 
} 

    public void initLoadingPanel(){ 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      loader = new JFrame("Loading...."); 
      ImageIcon img = new ImageIcon("loader.gif"); 
      loader.add(new JLabel(" Loading...", img, JLabel.CENTER)); 

      loader.setAlwaysOnTop(true); 
      loader.pack(); 
      loader.setSize(448, 497); 
      loader.setVisible(true); 
      loader.setLocationRelativeTo(null); 
     } 
    }); 
} 

回答

5

一般情況下,你應該只需要調用loader.dispose()loader.setVisible(false),這則引發了一個問題,你是如何加載你的資源?

您可能需要將loader的引用傳遞給您的代碼的這部分,因此完成後您可以處理該幀。

由於框架裝飾,用戶可以簡單地點擊「[X]」按鈕,關閉窗口,同時可以設置幀defaultCloseOperationDO_NOTHING_ON_CLOSE,它仍然看起來怪怪的。

你可以使用JFrame#setUndecorated

因爲loaderJFrame擴展它仍然可以爲用戶與父窗口交互(如果是可見的)上拆下框架裝飾,更好的解決方案可能是使用一個JDialog代替並使其成爲模態。

你也可以考慮在看看How to Create a Splash Screen一些其他的想法

更新

你遮蔽你的變量...

首先聲明loader作爲一個實例字段DataMigration

public class DataMigration extends JFrame{ 
    //... 
    private JFrame loader; 

B UT那麼你Runnable ....

SwingUtilities.invokeLater(new Runnable() { 
    @Override 
    public void run() { 
     JFrame loader = new JFrame("Loading...."); 

這意味着實例字段仍然是空,嘗試...

SwingUtilities.invokeLater(new Runnable() { 
    @Override 
    public void run() { 
     loader = new JFrame("Loading...."); 

,而不是...

run方法內重新申報其

也...

public void actionPerformed(ActionEvent arg0) { 
    initLoadingPanel(); 
    csv = FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText()); 
    generateTableList(csv.getCsvTitle(), stateController.getFieldNames()); 
    loader.dispose(); 
} 

是不會做你認爲它應該......你「可能會很幸運,loader框架會出現,但很可能它不會因爲您阻塞了事件分派線程。

相反,你應該考慮使用SwingWorker ....

initLoadingPanel(); 
SwingWorker worker = new SwingWorker<CVS, CVS>() { 

    @Override 
    protected CVS doInBackground() throws Exception { 
     return FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText()); 
    } 

    @Override 
    protected void done() { 
     try { 
      cvs = get(); 
      generateTableList(csv.getCsvTitle(), stateController.getFieldNames()); 
     } catch (ExecutionException ex) { 
      ex.printStackTrace(); 
     } 
     loader.dispose(); 
    } 

}; 
worker.execute(); 

(我不知道是什麼類型cvs,所以我猜...

這將確保數據加載時,您的UI將保持響應...

看看Concurrency in Swing

更新與工作的例子....

Example

import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.concurrent.ExecutionException; 
import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import static javax.swing.JFrame.EXIT_ON_CLOSE; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE; 

public class DataMigration extends JFrame { 

    private JFrame frmDataMigration; 

    private JFrame loader; 

    private JButton btnProcess; 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        DataMigration window = new DataMigration(); 
        window.frmDataMigration.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public DataMigration() { 
     initialize(); 
    } 

    private void initialize() { 

     frmDataMigration = new JFrame(); 

     btnProcess = new JButton("Load"); 
     btnProcess.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       initLoadingPanel(); 
       SwingWorker worker = new SwingWorker() { 

        @Override 
        protected Object doInBackground() throws Exception { 
         Thread.sleep(5000); 
         return "This is a test value used to highlight the example"; 
        } 

        @Override 
        protected void done() { 
         try { 
          get(); 
         } catch (ExecutionException ex) { 
         } catch (InterruptedException ex) { 
         } 
         loader.dispose(); 
         btnProcess.setEnabled(true); 
        } 

       }; 
       worker.execute(); 
       btnProcess.setEnabled(false); 
      } 
     }); 
     frmDataMigration.getContentPane().add(btnProcess); 
     frmDataMigration.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frmDataMigration.pack(); 
     frmDataMigration.setLocationRelativeTo(null); 
    } 

    public void initLoadingPanel() { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       loader = new JFrame("Loading...."); 
       ImageIcon img = new ImageIcon("loader.gif"); 
       loader.add(new JLabel(" Loading...", img, JLabel.CENTER)); 

       loader.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
       loader.setAlwaysOnTop(true); 
       loader.pack(); 
       loader.setSize(448, 497); 
       loader.setVisible(true); 
       loader.setLocationRelativeTo(null); 
      } 
     }); 

    } 
} 
+0

我遇到下面的錯誤,當我打電話loader.dispose()線程「AWT-EventQueue-0」中的異常java.lang.NullPointerException – newbie

+0

這是(大概)因爲你在'run'方法內的本地上下文中聲明瞭'loader'。而不是'JFrame loader = new JFrame(「Loading ....」);',你可以嘗試'loader = new JFrame(「Loading ....」);',假設'loader'被聲明爲一個實例變量。另外請注意,您應該在EDT的環境中調用'dispose'以及 – MadProgrammer

+0

請參閱我上面的代碼 – newbie