2016-01-13 69 views
0

在我的游戏对话框结束之后,可怕的弹出窗口会显示尖叫的噪音。当我点击按钮(BPanel)时,图片显示“损坏”,直到声音文件结束播放。尖叫声结束后,图片弹出。面板无法在Java Swing中同时显示声音文件

是否可以简单地将两者同步? 请注意,问题发生在使用Scaryface.png和Sound类的Woc类中。

主要方法:

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

public class Game { 
    public static void main(String args[]) { 
     Woc WineOrCheese = new Woc("Wine or Cheese"); 
     WineOrCheese.applyBackground("TitleBackground.png"); 
     WineOrCheese.applyButton("Play.png", 250, 200, 400, 200); 
    } 
} 

妇委会是JFrame的

import static java.lang.System.out; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 


public class Woc extends JFrame { 

private JFrame window; 
private Woc.BPanel background; 

private BufferedImage backgroundImg; 
final int HEIGHT = 600; 
final int WIDTH = 900; 
private BufferedImage scaryImg; 

public Woc(String text) { 
    /********************************* 
    * Sets up window. * 
    ********************************/ 
    window = new JFrame(text); 
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    window.setLayout(null); 

    window.setVisible(true); 
    window.setSize(WIDTH, HEIGHT); 
    window.setLocationRelativeTo(null); 
} 

public void applyBackground(String ImgName) { 
    try { 
     backgroundImg = ImageIO.read(getClass().getResource(ImgName)); 
    } catch (IOException e) { 
     out.println("No image detected"); 
    } 

    background = new Woc.BPanel(backgroundImg, 0, 0, WIDTH, HEIGHT); 

    window.add(background); 
    background.setBounds(0, 0, WIDTH, HEIGHT); 
} 

public void applyButton(String ImgName, int x1, int y1, int width, 
     int height) { 
    BufferedImage buttonImg = null; 
    try { 
     buttonImg = ImageIO.read(getClass().getResource(ImgName)); 
    } catch (IOException e) { 
    } 

    Woc.BPanel button = new Woc.BPanel(buttonImg, x1, y1, width, height); 

    window.add(button); 
    button.setBounds(0, 0, WIDTH, HEIGHT); 
    button.addMouseListener(new Clicker()); 

} 

public static void play(String filename) { 
    try { 
     Clip clip = AudioSystem.getClip(); 
     clip.open(AudioSystem.getAudioInputStream(new File(filename))); 
     clip.start(); 
    } catch (Exception exc) { 
     exc.printStackTrace(System.out); 
    } 
} 

private class BPanel extends JPanel { 
    public BufferedImage img; 
    public int x1, y1, width, height; 

    public BPanel(BufferedImage img, int x1, int y1, int width, int height) { 
     super(); 
     this.img = img; 
     this.x1 = x1; 
     this.y1 = y1; 
     this.width = width; 
     this.height = height; 
     // this.setOpaque(false); 
     this.setBackground(new Color(0, 0, 0, 0)); 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(img, x1, y1, width, height, null); 
    } 
} 

private class Clicker implements MouseListener { 

    @Override 
    public void mouseClicked(MouseEvent arg0) { 

     //Dialog of game is here in the form of JOptionPane. 

     applyBackground("Scaryface.png"); 
     for (int k = 0; k < 10; k++) { 
      for (int z = 0; z < 10; z++) { 
       out.println("."); 
      } 
     } 

     Sound scary = null; 
     try { 
      scary = new Sound("scary.wav", window); 
     } catch (Exception e) { 
     } 

    } 

    @Override 
    public void mouseEntered(MouseEvent arg0) { 

    } 

    @Override 
    public void mouseExited(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mousePressed(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mouseReleased(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

} 

Sound类:

import java.io.File; 
import java.io.IOException; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.FloatControl; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.UnsupportedAudioFileException; 
import javax.swing.*; 

public class Sound { 

    public Sound(String s, JFrame win) throws InterruptedException { 
     Clip play = null; 
     try { 
      File in = new File(s); 
      AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(in); 
      play = AudioSystem.getClip(); 
      play.open(audioInputStream); 
      FloatControl volume = (FloatControl) play.getControl(FloatControl.Type.MASTER_GAIN); 
      volume.setValue(1.0f); // Reduce volume by 10 decibels. 
      play.start(); 
      // Loop until the Clip is not longer running. 
      // We loop this way to allow the line to fill, otherwise isRunning will 
      // return false 
      do { 
       Thread.sleep(10); 
      } while (play.isRunning()); 
      play.drain(); 
     } catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex) { 
      ex.printStackTrace(); 
     } finally { 
      try { 
       play.close(); 
      } catch (Exception exp) { 
      } 
     } 
    } 
} 

顺便说一句,还有如何使我的游戏太多的任何提示更容易写?任何方法或类可以改善和缓解我必须经历的痛苦? (好吧罚款不真正的痛苦,但它仍然是痛苦的)

回答

2
do { 
    Thread.sleep(10); 
} while (play.isRunning()); 

play.drain(); 

卡住事件指派线程与被阻止被更新UI上述代码。有关更多详细信息,请参见Concurrency in Swing

避免使用null布局,像素完美布局是现代UI设计中的错觉。影响组件的个体大小的因素太多,其中没有一个可以控制。 Swing旨在与布局经理一起工作,放弃这些将导致问题和问题无法结束,您将花费越来越多的时间来尝试纠正

您不应该使用带按钮的MouseListener,但而不是一个ActionListener,有更多的方法来触发一个按钮。见How to Use Buttons, Check Boxes, and Radio ButtonsHow to Write an Action Listeners更多细节

如果你想知道什么时候声音已经完成,你应该使用LineListenerfor example。有了这个,你可以选择完成音频后该做什么。就个人而言,我会通过的LineListener的一个实例你Sound类,如您Sound类不应该关心其他任何事情,然后播放声音

没有while循环,声音无法播放。如何解决这个问题,因为这是我能够播放声音

不要关闭Clip,直到音频完成后的唯一途径,为此我会用(另一个)LineListener

以下示例基本上将您的Sound类应用到它并应用LineListener。一个用于通知感兴趣的一方(开始声音的人)关于线路事件,一个用于监视内部剪辑并在停止时关闭它。

的例子使用ReentrantLockCondition停止代码执行,直到剪辑已经完成,在这个例子中,将终止停止JVM,但你并不需要,我只是用来提供基本的示范

import java.io.File; 
import java.io.IOException; 
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.ReentrantLock; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.FloatControl; 
import javax.sound.sampled.LineEvent; 
import javax.sound.sampled.LineListener; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.UnsupportedAudioFileException; 

public class TestAudio { 

    public static void main(String[] args) { 
     ReentrantLock lockWait = new ReentrantLock(); 
     Condition conWait = lockWait.newCondition(); 
     try { 
      new Sound("...", new LineListener() { 
       @Override 
       public void update(LineEvent event) { 
        if (event.getType().equals(LineEvent.Type.STOP)) { 
         System.out.println("Line has stopped"); 
         lockWait.lock(); 
         try { 
          conWait.signal(); 
         } finally { 
          lockWait.unlock(); 
         } 
        } 
       } 
      }); 
      System.out.println("Waiting for audio to finish"); 
      lockWait.lock(); 
      try { 
       conWait.await(); 
      } finally { 
       lockWait.unlock(); 
      } 
      System.out.println("Audio has finished"); 
     } catch (InterruptedException | LineUnavailableException | IOException | UnsupportedAudioFileException exp) { 
      exp.printStackTrace(); 
     } 
    } 

    public static class Sound { 

     private Clip play; 

     public Sound(String s, LineListener listener) throws InterruptedException, LineUnavailableException, IOException, UnsupportedAudioFileException { 
      play = null; 
      File in = new File(s); 
      AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(in); 
      play = AudioSystem.getClip(); 
      play.addLineListener(new LineListener() { 
       @Override 
       public void update(LineEvent event) { 
        if (event.getType().equals(LineEvent.Type.STOP)) { 
         System.out.println("Audio stopped, closing clip"); 
         play.close(); 
        } 
       } 
      }); 
      play.addLineListener(listener); 
      play.open(audioInputStream); 
      FloatControl volume = (FloatControl) play.getControl(FloatControl.Type.MASTER_GAIN); 
      volume.setValue(1.0f); // Reduce volume by 10 decibels. 
      play.start(); 
     } 
    } 

} 

对于更复杂的例子,使用Swing和Clip,看看Playing multiple sound clips using Clip objects

+0

没有while循环,声音无法播放。我该如何解决这个问题,因为这是我能够播放声音的唯一方式。 –

+0

不要关闭'剪辑' – MadProgrammer

+0

我已经尝试了很多东西(我读过教程),但我找不到方法。有什么建议么? –