A friend recently asked me to make a simple Buzzer program and has found a strange "bug" in what I wrote for him.
If a key is pushed and the buzzer is reset rapidly over the course of a few seconds he observes a 2 to 3 second freeze of the program that occurs between the the first key press after the reset and the "buzz" indication. He has the following Java installation:
build 1.7.0_25-b16
However, I do not experience this problem on my computer, with the following Java installation:
$ java -version
java version "1.6.0_51"
Java(TM) SE Runtime Environment (build 1.6.0_51-b11-457-10M4509)
Java HotSpot(TM) 64-Bit Server VM (build 20.51-b01-457, mixed mode)
Upon unfreeze, the program returns the appropriate key (that is, not the last key pressed, but the first one pushed after the reset and before the freeze). This suggests that the problem is not with the listener but with the reaction to the listener.
Any thoughts on what might be causing this phenomenon? Thanks in advance for your help.
Source code:
/**
* Buzzer.java
*
* Buzzer
*/
package org.lexingtonma.lhs.nhb;
import java.awt.Color;
import java.awt.DefaultKeyboardFocusManager;
import java.awt.Font;
import java.awt.KeyEventDispatcher;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* @author Arman D. Bilge
*
*/
public class Buzzer extends JFrame implements KeyListener {
private static final long serialVersionUID = 7492374642744742658L;
private static final String BUZZ_A = "BuzzA.wav";
private static final String BUZZ_B = "BuzzB.wav";
private Clip buzz = null;
private boolean listening = true;
private final JTextField display = new JTextField(3);
private final JButton reset = new JButton("Reset");
{
DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventDispatcher(new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
keyTyped(e);
return false;
}
});
setTitle("Buzzer");
final JPanel panel = new JPanel();
setSize(256, 162);
setDefaultCloseOperation(EXIT_ON_CLOSE);
display.setFont(new Font("Helvetica", Font.BOLD, 64));
display.setForeground(Color.WHITE);
display.setVisible(true);
display.setEditable(false);
display.setHorizontalAlignment(JTextField.CENTER);
panel.add(display);
reset.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
display.setText("");
display.setBackground(Color.WHITE);
listening = true;
reset.setEnabled(false);
}
});
reset.setEnabled(false);
panel.add(reset);
add(panel);
try {
buzz = AudioSystem.getClip();
} catch (LineUnavailableException e) {
JOptionPane.showMessageDialog(this, e.getLocalizedMessage(), "FATAL ERROR", JOptionPane.ERROR_MESSAGE);
}
}
public static final void main(String args[]) {
Buzzer b = new Buzzer();
b.setVisible(true);
}
public void keyPressed(KeyEvent e) {
// Do nothing
}
public void keyReleased(KeyEvent e) {
// Do nothing
}
public void keyTyped(KeyEvent e) {
final char c = e.getKeyChar();
if (listening && Character.isLetterOrDigit(c)) {
buzz.close();
listening = false;
if (Character.isDigit(c)) {
display.setBackground(Color.RED);
try {
buzz.open(AudioSystem.getAudioInputStream(getClass().getResource(BUZZ_A)));
buzz.start();
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex.getLocalizedMessage(), "FATAL ERROR", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
} else {
display.setBackground(Color.BLUE);
try {
buzz.open(AudioSystem.getAudioInputStream(getClass().getResource(BUZZ_B)));
buzz.start();
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex.getLocalizedMessage(), "FATAL ERROR", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
}
display.setText("" + c);
reset.setEnabled(true);
}
}
}