Java StdAudio类使我的JFrame不显示
我想写一个能演奏和弦的程序。我想添加一个窗口,显示一个进度条,显示和弦弹奏的时间和完成的时间。为了弹奏和弦,我使用了一个稍微修改过的版本。到目前为止,当我要求和弦演奏时,我有以下代码要运行Java StdAudio类使我的JFrame不显示,java,multithreading,swing,event-dispatch-thread,Java,Multithreading,Swing,Event Dispatch Thread,我想写一个能演奏和弦的程序。我想添加一个窗口,显示一个进度条,显示和弦弹奏的时间和完成的时间。为了弹奏和弦,我使用了一个稍微修改过的版本。到目前为止,当我要求和弦演奏时,我有以下代码要运行 public static void playNotes(double[] frequencies, double duration, double amplitude) { PlayAudioGUI g = new PlayAudioGUI(duration); g.run();
public static void playNotes(double[] frequencies, double duration, double amplitude)
{
PlayAudioGUI g = new PlayAudioGUI(duration);
g.run();
amp = amplitude;
ArrayList<double[]> chord = new ArrayList<double[]>();
for(double freq : frequencies) {
double[] note = StdAudio.tone(freq, duration);
chord.add(note);
}
double[] chordCombined = new double[chord.get(0).length];
for (int i = 0; i < chordCombined.length; i++) {
for (double[] note : chord) {
chordCombined[i] += note[i];
}
chordCombined[i] /= chord.size();
}
StdAudio.play(chordCombined);
}
感谢您的帮助。建议:
- 新的依赖对话框窗口应该是一个对话框,比如JDialog,而不是一个新的JFrame,它正在创建一个单独的应用程序
- 您知道您应该在后台线程中创建声音,而您的空白屏幕正是由这个问题造成的,但我在代码中没有看到线程创建——为什么
- 我自己不会使用Swing计时器和轮询数据,而是在SwingWorker中完成所有工作,在SwingWorker的
方法中,我会更新其进度状态,并向SwingWorker添加PropertyChangeListener并监视此状态doInBackground
- 顺便说一句,您几乎不想创建一个可运行的类,然后调用它的
方法。如果要创建Runnable以允许它在后台线程中运行,则可能会将其放入线程中,然后在线程上调用run()
。因为上面的代码应该在Swing事件线程上运行,所以如果没有从该线程调用它,那么应该通过start()
SwingUtilities.invokeLater(myRunnable)将其排入队列代码>
- 我不确定如何从StdAudio库中获得进度值。如果有办法,那么使用它通过其
方法设置SwingWorker的进度状态。如果没有,那么你可以猜,或者你最好使用不确定的进度条。我相信JProgressBar有一个名为setProgress(…)
的方法可以解决这个问题setUndeterminate(true)
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.Timer;
public class PlayAudioGUI implements Runnable {
private JFrame window;
private JProgressBar prog;
private double duration;
private Timer t;
class TimerListener implements ActionListener {
// This runs every few milliseconds, depending on the delay set below
public void actionPerformed(ActionEvent event) {
prog.setValue(prog.getValue() + 1);
// Stop the timer and hide the window when the progress bar
// completes
if (prog.getValue() == prog.getMaximum()) {
t.stop();
window.setVisible(false);
}
}
}
public PlayAudioGUI(double duration) {
this.window = new JFrame("Playing audio...");
this.duration = duration;
}
@Override
public void run() {
// Setting up gridbag layout. I will add more components later.
Container pane = this.window.getContentPane();
pane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(30, 30, 30, 30);
// Display the approximate duration
String clippedDuration;
if (Double.toString(duration).length() > 5) {
clippedDuration = Double.toString(duration).substring(0, 4);
} else {
clippedDuration = Double.toString(duration);
}
String message = "Playing audio for " + clippedDuration + " seconds";
pane.add(new JLabel(message), c);
// Make a progressbar
c.gridy = 1;
this.prog = new JProgressBar();
this.prog.setMinimum(0);
this.prog.setMaximum(250);
pane.add(this.prog, c);
// More window management stuff
this.window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.window.pack();
this.window.setVisible(true);
// Set up the timer
ActionListener listener = new TimerListener();
final int DELAY = (int) (4 * this.duration); // This works, I did the
// math :)
t = new Timer(DELAY, listener);
t.start();
}
}