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的
    doInBackground
    方法中,我会更新其进度状态,并向SwingWorker添加PropertyChangeListener并监视此状态
  • 顺便说一句,您几乎不想创建一个可运行的类,然后调用它的
    run()
    方法。如果要创建Runnable以允许它在后台线程中运行,则可能会将其放入线程中,然后在线程上调用
    start()
    。因为上面的代码应该在Swing事件线程上运行,所以如果没有从该线程调用它,那么应该通过
    SwingUtilities.invokeLater(myRunnable)将其排入队列
  • 我不确定如何从StdAudio库中获得进度值。如果有办法,那么使用它通过其
    setProgress(…)
    方法设置SwingWorker的进度状态。如果没有,那么你可以猜,或者你最好使用不确定的进度条。我相信JProgressBar有一个名为
    setUndeterminate(true)
    的方法可以解决这个问题

不要阻止EDT(事件调度线程)。发生这种情况时,GUI将“冻结”。有关详细信息和修复方法,请参阅。如果我的回答中有什么让您感到困惑,请询问。
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();
    }
}