我有一个程序,我为一个朋友做了一段时间,我有一个计时器和闹钟的功能。它会在您启动计时器时播放一个声音并显示一个图像,并在计时器结束时播放另一个声音和图像。它一直运行良好(或多或少),但我的朋友最近切换到Linux,并有一些更具交互性的声音控制器,这导致我们发现了该程序的一个问题:每次播放声音时,它都会创建一个全新的输入流,该输入流不会被重用,直到程序完全关闭时才会消失。这不仅是我的这个糟糕的设计,我想要学习如何修复,而且当我的朋友试图多次使用计时器而没有关闭程序时,它也会导致问题。我相信修复方法是让所有声音都通过一个输入流播放(如果有人对Java和Linux的交互有更多了解,请指正我)。我尝试简单地将AudioInputStream设置为全局变量,并在每次使用之前重新设置它,但这会导致图像和声音完全停止工作,我不知道为什么。下面是我当前和有缺陷的代码中的actionPerformed on按钮按下。下面是有效但无效的代码。
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
boolean needNewThread = false;
if (imgWindow.getIcon() == null) {
needNewThread = true;
}
timeUpLabel.setText(" ");
BufferedImage buffImg = null;
try{
globalAudioIn.reset();
URL url = this.getClass().getResource("/EvilManiMani.wav");
globalAudioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(globalAudioIn);
clip.start();
buffImg = ImageIO.read(getClass().getResource("/images/cloudWait.png"));
imgWindow.setIcon(new ImageIcon(buffImg));
System.out.println(buffImg.toString());
} catch (Exception e){
System.out.println(e.getMessage());
}
Integer inputTime = Integer.parseInt(timeTextField.getText());
timerLabel.setText(inputTime + ":00");
if(needNewThread) {
t = new Timer(1000, new ActionListener (){
@Override
public void actionPerformed(ActionEvent ae){
String[] minsAndSeconds = timerLabel.getText().split(":");
boolean timesUp = false;
if(minsAndSeconds[0].startsWith("-")) {
timesUp = true;
String temp = minsAndSeconds[0].substring(1);
minsAndSeconds[0] = temp;
}
Integer minutes = Integer.parseInt(minsAndSeconds[0]);
Integer seconds = Integer.parseInt(minsAndSeconds[1]);
seconds += (minutes*60);
if(seconds > 0 && !timesUp){
minutes = --seconds/60;
seconds %= 60;
if(seconds >= 10) {
timerLabel.setText(minutes + ":" + seconds);
}else {
timerLabel.setText(minutes + ":0" + seconds);
}
}else if(seconds > 0 && timesUp) {
minutes = ++seconds/60;
seconds %= 60;
if(seconds >= 10) {
timerLabel.setText("-" + minutes + ":" + seconds);
}else {
timerLabel.setText("-" + minutes + ":0" + seconds);
}
}else if (seconds == 0){
timerLabel.setText("-0:01");
BufferedImage bufferedImg = null;
try {
globalAudioIn.reset();
URL url = this.getClass().getResource("/YouWin!.wav");
globalAudioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(globalAudioIn);
clip.start();
bufferedImg = ImageIO.read(getClass().getResource("/images/drinkyMattPog.png"));
imgWindow.setIcon(new ImageIcon(bufferedImg));
timeUpLabel.setText("Time's up");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
});
t.setRepeats(true);
t.start();
}
}有效但无效:
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
boolean needNewThread = false;
if (imgWindow.getIcon() == null) {
needNewThread = true;
}
timeUpLabel.setText(" ");
BufferedImage buffImg = null;
try{
URL url = this.getClass().getResource("/EvilManiMani.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
buffImg = ImageIO.read(getClass().getResource("/images/cloudWait.png"));
imgWindow.setIcon(new ImageIcon(buffImg));
System.out.println(buffImg.toString());
} catch (Exception e){
System.out.println(e.getMessage());
}
Integer inputTime = Integer.parseInt(timeTextField.getText());
timerLabel.setText(inputTime + ":00");
if(needNewThread) {
t = new Timer(1000, new ActionListener (){
@Override
public void actionPerformed(ActionEvent ae){
String[] minsAndSeconds = timerLabel.getText().split(":");
boolean timesUp = false;
if(minsAndSeconds[0].startsWith("-")) {
timesUp = true;
String temp = minsAndSeconds[0].substring(1);
minsAndSeconds[0] = temp;
}
Integer minutes = Integer.parseInt(minsAndSeconds[0]);
Integer seconds = Integer.parseInt(minsAndSeconds[1]);
seconds += (minutes*60);
if(seconds > 0 && !timesUp){
minutes = --seconds/60;
seconds %= 60;
if(seconds >= 10) {
timerLabel.setText(minutes + ":" + seconds);
}else {
timerLabel.setText(minutes + ":0" + seconds);
}
}else if(seconds > 0 && timesUp) {
minutes = ++seconds/60;
seconds %= 60;
if(seconds >= 10) {
timerLabel.setText("-" + minutes + ":" + seconds);
}else {
timerLabel.setText("-" + minutes + ":0" + seconds);
}
}else if (seconds == 0){
timerLabel.setText("-0:01");
BufferedImage bufferedImg = null;
try {
URL url = this.getClass().getResource("/YouWin!.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
bufferedImg = ImageIO.read(getClass().getResource("/images/drinkyMattPog.png"));
imgWindow.setIcon(new ImageIcon(bufferedImg));
timeUpLabel.setText("Time's up");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
});
t.setRepeats(true);
t.start();
}
} 谢谢!此外,欢迎对代码提出任何建设性的批评,无论它是否与问题相关。
发布于 2021-09-15 01:09:41
在调用clip.start()之前,添加一个侦听器以关闭剪辑和AudioInputStream:
clip.open(audioIn);
clip.addLineListener(e -> {
if (e.getType().equals(LineEvent.Type.STOP)) {
clip.close();
try {
audioIn.close();
} catch (IOException e) {
System.err.println(e);
}
}
});
clip.start();既然你已经要求了建设性的批评:永远不要写catch (Exception)。您不希望捕获RuntimeException或它的子类,因为它们通常指示需要暴露和修复的程序员错误,而不是掩饰。在您的例子中,您应该使用catch (LineUnavailableException | IOException e)。
catch块不应打印e.getMessage()。相反,使用e.printStackTrace(),因此如果发生异常,您将确切地知道发生了什么以及发生在哪里。
https://stackoverflow.com/questions/69184459
复制相似问题