Reputation: 37
I'm creating a program that plays a sequence of notes on a piano and then determines whether the user's clicks on the piano match what was just played. I got the program to play a sequence of notes automatically using a Swing timer, but I need it to wait until the sequence is done playing before it continues. Here's a simplified example of what I have now:
import java.awt.event.*;
import javax.swing.*;
public class myProgram {
Timer timer = new Timer(1000, new AutoPlay());
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myProgram myProgram = new myProgram();
System.out.println("Computer plays notes.");
myProgram.compTurn();
System.out.println("Your turn.");
}
});
}
class AutoPlay implements ActionListener {
int i = 0;
public void actionPerformed(ActionEvent e) {
System.out.println("Auto-played note.");
i++;
if (i == 2) timer.stop();
}
}
// TODO - Play a melody for the user to repeat
public void compTurn() {
timer.start();
}
}
"Your turn" prints too soon. If it helps, the point of the timer is to have the program trigger an audio note, update the piano graphic so you can see the pressed note, load up the next note that will be played, and repeat until the sequence is complete.
Upvotes: 1
Views: 166
Reputation: 285450
Use a variant of the observer pattern to be notified of when the timer is done. For instance a PropertyChangeListener would work nicely. For example...
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class MyProg2 extends JPanel {
public static final String TIMER_COMPLETE = "timer complete";
private static final int TIMER_DELAY = 1000;
private Timer timer;
public MyProg2() {
// TODO create GUI
}
public void playNotes() {
if (timer != null && timer.isRunning()) {
return;
}
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
private class TimerListener implements ActionListener {
private int i = 0;
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Auto-played note.");
i++;
if (i == 2) {
timer.stop();
firePropertyChange(TIMER_COMPLETE, false, true);
}
}
}
private static void createAndShowGui() {
System.out.println("Starting program");
MyProg2 mainPanel = new MyProg2();
mainPanel.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (MyProg2.TIMER_COMPLETE.equals(pcEvt.getPropertyName()) && pcEvt.getNewValue() == Boolean.TRUE) {
System.out.println("Your turn");
}
}
});
mainPanel.playNotes();
JFrame frame = new JFrame("MyProg2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Upvotes: 1
Reputation: 12462
Disable user input options when the computer starts playing. Enable them when it is the users turn. Never disable the edt.
Upvotes: 1