2015-02-03 5 views
0

У меня есть проблема с отображением загрузчика во время тяжелой загрузки данных по основной программе. Ниже приведен класс под названием SplashScreen, который отображает анимацию .gif загрузчика.Swing Создать загрузчик в потоке без блокировки GUI

общественного класс SplashScreen расширяет JWindow {

public SplashScreen() { 
    super(); 
    Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resources/load.gif")); 
    try { 
     if (image != null) { 
      JLabel imageLabel = new JLabel(); 
      imageLabel.setIcon(new ImageIcon(image)); 
      this.getContentPane().setLayout(new BorderLayout()); 
      this.getContentPane().add(imageLabel, BorderLayout.CENTER); 
      this.pack(); 
      Dimension screenSize = 
        Toolkit.getDefaultToolkit().getScreenSize(); 
      Dimension labelSize = imageLabel.getPreferredSize(); 
      setLocation(screenSize.width/2 - (labelSize.width/2), 
        screenSize.height/2 - (labelSize.height/2)); 
      addMouseListener(new MouseAdapter() { 
       public void mouseClicked(MouseEvent e) { 
        dispose(); 
       } 
      }); 
      addKeyListener(new KeyAdapter() { 
       public void keyTyped(KeyEvent e) { 
        dispose(); 
       } 
      }); 
     } 
    } catch (Exception ex) { 
    } 
} 

Существует результат работы этого куска кода:

Loader gif

Но когда я хотел бы загрузить много данных (скажем, 1 milion records) У меня есть что-то вроде этого:

Loader gif blank

Я использовал Thread, EventQueue.invokeLater и SwingUtilities, чтобы показать SplashScreen в отдельном потоке, но он не работает. Когда я загружаю тяжелые данные, он всегда пуст. К сожалению, я должен сказать, что использование EventQueue или SwingUtilities довольно сложно, поскольку вы не можете завершить задачи, запущенные этими утилитами.

+3

invokeLater выполнит runnable, в какой-то момент в будущем, с контекстом EDT, это точка. Вместо этого попробуйте запустить ваш блокирующий код в SwingWorker вместо – MadProgrammer

+2

Для [пример] (http://stackoverflow.com/a/25526869/230513). – trashgod

+0

Спасибо! Это то, что я искал! Очень признателен ;) –

ответ

0

Я, наконец, понял, как правильно реализовать этот случай.

1) Реализация SplashScreen, который будет отображать загрузчик (.gif)

public class SplashScreen extends JWindow { 

     public SplashScreen() { 
      super(); 
      Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resources/load.gif")); 
      try { 
       if (image != null) { 
        JLabel imageLabel = new JLabel(); 
        imageLabel.setIcon(new ImageIcon(image)); 
        this.getContentPane().setLayout(new BorderLayout()); 
        this.getContentPane().add(imageLabel, BorderLayout.CENTER); 
        this.pack(); 
        Dimension screenSize = 
          Toolkit.getDefaultToolkit().getScreenSize(); 
        Dimension labelSize = imageLabel.getPreferredSize(); 
        setLocation(screenSize.width/2 - (labelSize.width/2), 
          screenSize.height/2 - (labelSize.height/2)); 
        addMouseListener(new MouseAdapter() { 
         public void mouseClicked(MouseEvent e) { 
          dispose(); 
         } 
        }); 
        addKeyListener(new KeyAdapter() { 
         public void keyTyped(KeyEvent e) { 
          dispose(); 
         } 
        }); 
       } 
      } catch (Exception ex) { 
      } 
     } 

     @Override 
     public void dispose() { 
      setVisible(false); 
     } 
} 

2) Иниц ScheduledExecutorService

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 

3) Реализовать тему ответственного за показ SplashScreen

Thread splashThread = new Thread(new Runnable() { 
      public void run() { 
       setSplashScreen(new SplashScreen()); 
       getSplashScreen().setVisible(true); 
       getSplashScreen().toFront(); 
       getSplashScreen().setAlwaysOnTop(true); 
      } 
     }); 

4) Расписание new created Тема:

executor.schedule(splashThread, 0, TimeUnit.MILLISECONDS); 

5) Когда есть необходимость утилизации SplashScreen

getSplashScreen().dispose(); 

Кроме того, вы можете создать отдельную тему, чтобы проверить, есть ли необходимость в утилизации SplashScreen.

private void invokeExecutor() { 
    executor.scheduleAtFixedRate(new DoneTask(), 0, 200, TimeUnit.MILLISECONDS); 
} 

private class DoneTask implements Runnable { 
    @Override 
    public void run() { 
     if (fileWorker.isDone()) { //SwingWorker 
      getSplashScreen().dispose(); 
     } 
    } 
}