2013-02-10 5 views
0

Я пытаюсь сделать свой собственный индикатор выполнения на моем заставке. Создание мой экран заставки было легко:Заставка Заставка не работает

Java -splash: EaseMailMain.jpg Main.class (от Eclipse)

Первая строка моего основного метода называет это:

new Thread(new Splash()).start(); 

И это класс выплеска:

public class Splash implements Runnable { 
    public volatile static int percent = 0; 
    @Override 
    public void run() { 
     System.out.println("Start"); 
     final SplashScreen splash = SplashScreen.getSplashScreen(); 
     if (splash == null) { 
      System.out.println("SplashScreen.getSplashScreen() returned null"); 
      return; 
     } 
     Graphics2D g = splash.createGraphics(); 
     if (g == null) { 
      System.out.println("g is null"); 
      return; 
     } 
     int height = splash.getSize().height; 
     int width = splash.getSize().width; 
     //g.drawOval(0, 0, 100, 100); 
     g.setColor(Color.white); 
     g.drawRect(0, height-50, width, 50); 
     g.setColor(Color.BLACK); 
     while(percent <= 100) { 
      System.out.println((width*percent)/100); 
      g.drawRect(0, height-50, (int)((width*percent)/100), 50); 
      percent += 1; 
      try { 
       Thread.sleep(50); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

Я не получить какие-либо ошибки, но я получаю небольшую коробку под ним:

The image with a rectangle below.

Если я изменяю drawRects в (0, 0, ширина, высота) не делает никакой разницы.

Я пытался ссылаться на качелях EDT с:

SwingUtilities.invokeAndWait((new Splash())); 

Но ничего не происходит.

Может ли кто-нибудь увидеть проблему? Или знаете, как это исправить?

+2

Я не могу попробовать это (таким образом, комментарий), но я был бы осторожен с линией: '(width * percent)/100', так как это все операции с целыми числами. – sdasdadas

+0

Это верный момент, я брошу 100, чтобы удвоить. – Adude11

+0

Вы можете просто написать 100.0. – sdasdadas

ответ

4

Вы должны использовать SwingUtilities.invokeLater или SwingUtilities.invokeAndWait при обновлении графического интерфейса пользователя из другой темы.

См. Главу Concurrency in Swing, в которой объясняются причины этого.

SplashScreen Example из учебника содержит Thread.sleep внутри резьбы Swing. Это тоже хорошо, если вам не нужно какое-либо другое обновление GUI во время показа SplashScreen. Однако ваш код загрузки должен происходить в другом потоке.

Я бы порекомендовал добавить в свой класс установщика setPercent, который создает Runnable для обновления GUI через SwingUtilities.invokeLater. Таким образом, вам даже не нужно опросить переменную percent, а SwingThread также может отображать другие элементы интерфейса.

+0

Ой забыл добавить этот бит, я уже проверил это, это не имеет значения. – Adude11

+1

@ Adude11 Из вашего примера кода, вы этого не сделали, или, по крайней мере, нет, вы не сделали этого правильно ... Я продлил рекомендации bikeshedder (+1) и попытался расширить причины, re есть проблема. Если вы сочтете это полезным, я бы подгонял голосование, но вы должны отдать должное bikeshedder за выявление проблемы (отметьте их ответ как правильный). – MadProgrammer

3

Bikeshedder прав (+1), вы блокируете EDT.

while(percent <= 100) { 
    System.out.println((width*percent)/100); 
    g.drawRect(0, height-50, (int)((width*percent)/100), 50); 
    percent += 1; 
    try { 
     Thread.sleep(50); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

Использование SwingUtilities.invokeAndWait((new Splash())); размещает Runnable на очереди событий, то есть, когда вы вводите свой while цикл и Thread.sleep, вы предотвращения очереди событий от диспетчерских новых событий, в том числе перекрашивать запросов

Вы должны используйте что-то вроде SwingWorker для выполнения вашей фактической загрузки (в фоновом потоке), публикуя результаты выполнения, которые могут отображать заставки ...

enter image description here

public class TestSplashScreen { 

    public static void main(String[] args) { 
     new TestSplashScreen(); 
    } 

    public TestSplashScreen() { 
     SplashScreenWorker worker = new SplashScreenWorker(); 
     worker.execute(); 
     try { 
      worker.get(); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     System.out.println("All Done..."); 
//  Launch main application... 
//  SwingUtilities.invokeLater(...); 
    } 

    public class SplashScreenWorker extends SwingWorker<Void, Float> { 

     private SplashScreen splash; 

     public SplashScreenWorker() { 
      splash = SplashScreen.getSplashScreen(); 
      if (splash == null) { 
       System.out.println("SplashScreen.getSplashScreen() returned null"); 
       return; 
      } 
     } 

     @Override 
     protected void process(List<Float> chunks) { 
      Graphics2D g = splash.createGraphics(); 
      if (g == null) { 
       System.out.println("g is null"); 
       return; 
      } 
      float progress = chunks.get(chunks.size() - 1); 
      int height = splash.getSize().height; 
      int width = splash.getSize().width; 
      g.setComposite(AlphaComposite.Clear); 
      g.fillRect(0, 0, width, height); 
      g.setPaintMode(); 
      g.setColor(Color.WHITE); 
      g.drawRect(0, height - 50, width, 50); 
      g.setColor(Color.RED); 
      int y = height - 50; 
      g.fillRect(0, y, (int) (width * progress), 50); 
      FontMetrics fm = g.getFontMetrics(); 
      String text = "Loading Microsoft Windows..." + NumberFormat.getPercentInstance().format(progress); 
      g.setColor(Color.WHITE); 
      g.drawString(text, (width - fm.stringWidth(text))/2, y + ((50 - fm.getHeight())/2) + fm.getAscent()); 
      g.dispose(); 
      splash.update(); 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      for (int value = 0; value < 1000; value++) { 

       float progress = value/1000f; 
       publish(progress); 
       Thread.sleep(25); 

      } 
      return null; 
     } 
    } 
} 
Смежные вопросы