面板无法与Java Swing中的声音文件同时显示 [英] Panel Fails to Show Up Concurrently with Sound File In Java Swing
问题描述
在我的游戏对话框结束后,一个可怕的弹出窗口似乎会发出刺耳的声音.当我单击按钮(BPanel)时,图片显示为损坏",直到声音文件播放完毕.尖叫结束后,图片弹出.
是否可以将两者简单地同步在一起? 请注意,该问题发生在使用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);
}
}
Woc是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
}
}
声音类:
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) {
}
}
}
}
顺便说一下,有什么技巧可以使我的游戏更容易编写?有什么方法或类可以改善和减轻我必须经历的痛苦吗? (好的,不是真正的痛苦,但仍然很痛苦)
do {
Thread.sleep(10);
} while (play.isRunning());
和
play.drain();
正在使用上述代码阻止事件分发线程,从而阻止了UI的更新.有关更多详细信息,请参见 Swing中的并发
避免使用null
布局,像素完美布局是现代ui设计中的一种幻觉.有太多因素会影响组件的单个大小,您无法控制. Swing旨在与布局管理者为核心一起工作,舍弃这些问题不会导致任何问题,而您将花费越来越多的时间进行纠正
您不应该在按钮上使用MouseListener
,而是在ActionListener
上触发按钮.请参见如何使用按钮,复选框和单选按钮和如何编写动作监听器以获取更多详细信息>
如果您想知道音频何时结束,则应该使用 对于更复杂的示例,使用Swing和 Is it possible to simply synchronize the two together?
Note that the problem is happening in the Woc class where Scaryface.png and the Sound class is used. Main method: Woc is the JFrame Sound class: By the way, are there any tips of how to make my game much easier to write? Any methods or classes that can improve and ease the pain I have to go through to? (Okay fine not real pain but it's still painful) and Are blocking the Event Dispatching Thread with the aforementioned code which is preventing the UI from been updated. See Concurrency in Swing for more details Avoid using You shouldn't be using a If you want to know when the audio has finished, you should be using a Without the while loop, the sound is unable to play. How do I resolve this issue because this was the only way I was able to play the sound Don't close the The following example basically takes your The example use a For a more complex example, using Swing and 这篇关于面板无法与Java Swing中的声音文件同时显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!LineListener
,Clip
,请查看
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);
}
}
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
}
}
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) {
}
}
}
}
do {
Thread.sleep(10);
} while (play.isRunning());
play.drain();
null
layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectifyMouseListener
with buttons, but instead a ActionListener
, there is more then one way to trigger a button. See How to Use Buttons, Check Boxes, and Radio Buttons and How to Write an Action Listeners for more detailsLineListener
, for example. With this, you can choose what to do when the audio has completed. Personally, I would pass the an instance of LineListener
to your Sound
class, as your Sound
class shouldn't care about anything other then playing the sound
Clip
until after the audio has completed, for this I would use (another) LineListener
.Sound
class and applies a LineListener
to it. One is used to notified the interested party (the one who started the sound) about line events and one is used to monitor the clip internally and close it when it stops.ReentrantLock
and Condition
to stop the code execution until the clip has completed, in this example, this will stop the JVM from terminating, but you don't need, I just used to provide a basic demonstrationimport 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();
}
}
}
Clip
, have a look at Playing multiple sound clips using Clip objects