2016-01-13 40 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

我已經嘗試了很多東西(我讀過教程),但我找不到方法。有什麼建議麼? –