2014-05-17 18 views
0

我正在尝试制作一个应用程序,用于检索图像和.mp3文件,并在音频完成后从一个图像切换到下一个图像。我在这些图像之间转换的底层框架有点复杂,但我设法在SWT中获得了一个成功的操作,使我能够手动从一个转换到另一个。但是,当我尝试将其自动化时,出现了一个问题;当放置到一个循环中时,我的playAudio()方法在我的displayShow()方法所做的所有调用都已解决之前就开始了,这会导致一个空白窗口,尽管音频仍在播放。JLayer Player放置在循环中时覆盖SWT小部件的refesh

这里是我要开始表演动作的run方法:

  Action startAction = new Action("Start") { 
      public void run() { 

       //do { 
        displayShow(); 
        playAudio(); 
       //} while(true);    
      } 
     }; 

这里是playAudio()。我能够播放音频平安无事:

public void playAudio() { 

    final String audio = "Happy_Birthday.mp3"; 
    audioLatch = new CountDownLatch(1); 
    audioThread = new Thread() { 
     public void run() { 

      try {    
       Player player = new Player 
            (new BufferedInputStream 
             (new FileInputStream(audio))); 

       player.play(); 
       audioLatch.countDown(); 

      } catch (JavaLayerException e) { 

      } catch (FileNotFoundException e) { 

      } catch (Exception e) { 

      } 
     } 
    }; 
    audioThread.start(); 
    try { 
     audioLatch.await(); 
    } catch (InterruptedException e) { 

    } 
} 

这里是displayShow():

private void displayShow() { 

    new Thread() { 
     public void run() { 
      Display.getDefault().asyncExec(new Runnable() { 
       public void run() { 
        Control[] children = container.getChildren(); 

        for (int i = 0; i < children.length; i++) { 
         children[i].dispose(); 
        } 

        show.showSlide(container); 
        container.layout(); 
       } 
      }); 
     } 
    }.start(); 
} 

show.showSlide返回复合,其父母为容器,这是最高的直接子父母组合。在新创建的组合中,将图像添加到标签,并将标签的父级分配给组合。我意识到displayShow()是否在单独的线程中似乎不重要;这只是我尝试的最后一件事。

这不仅仅是增加了导致刷新不执行的循环。我可以通过playAudio()方法删除CountDownLatch,我可以让手动转换工作。如果我删除这个锁存器,将这两个方法封装在一个循环中的唯一方法是嵌入while循环,这似乎占用了相当数量的CPU,但仍然无法解决我的问题。我错过了什么?

回答

0

audioLatch.await()正在阻塞主程序线程,这是所有SWT操作运行的线程,因此Display.asyncExec可运行列表只会在线程可用前排队。

如果你真的必须在playAudio方法等待,直到后台线程完成你可以有运行显示事件循环:

while (! background thread finished) 
{ 
    if (!display.readAndDispatch()) 
    display.sleep(); 
} 
+0

这工作,非常感谢你。我在演奏音乐的过程中等待并不是必须的。你会在哪里做到这一点? –

+0

我有一个基于JavaZoom BasicPlayer的播放器 - 它使用监听器在播放器线程完成时通知主线程。因此,您在播放开始时禁用“播放”按钮,并在侦听器被调用播放结束时再次启用。 –

+0

按照您第一次建议的方式完成后,在每次转换后,音频结束和下一次移动之间的等待时间似乎正在增加。有没有办法强制显示屏醒来? –