java - StdAudio 类使我的 JFrame 不显示

标签 java multithreading swing event-dispatch-thread

我正在尝试编写一个播放音乐和弦的程序。我想添加一个窗口,显示一个进度条,显示和弦演奏的时间以及它们已完成的程度。为了演奏和弦,我一直使用 StdAudio class 的稍微修改版本。 。到目前为止,当我要求演奏和弦时,我需要运行以下代码。

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);
}

我以前从未尝试过多线程,所以我不知道我做错了什么。当我运行代码时,它在播放和弦时显示一个空窗口,然后正确显示该窗口。我希望它在播放音频的同时显示窗口。

这是我的窗口类代码。

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();
    }
}

感谢您的帮助。

最佳答案

建议:

  • 新的依赖对话框窗口应该只是一个对话框,例如 JDialog,而不是创建整个独立应用程序的新 JFrame。
  • 您知道您应该在后台线程中创建声音,而您的黑屏正是由这个问题引起的,但我在您的代码中没有看到任何线程创建 - 为什么?
  • 我自己,我不会使用 Swing Timer 和轮询数据,而是在 SwingWorker 中完成所有操作,在 SwingWorker 的 doInBackground 方法中,我会更新其进度状态,并且我会将 PropertyChangeListener 添加到 SwingWorker 并监视此状态。
  • 顺便说一句,您几乎永远不会想创建一个 Runnable 类,然后调用它的 run() 方法。如果您要创建 Runnable 以允许其在后台线程中运行,那么您可能会将其放入线程中,然后在该线程上调用 start()。由于上面的代码应该在 Swing 事件线程上运行,因此如果不是从此线程调用它,则应该通过 SwingUtilities.invokeLater(myRunnable);
  • 将其排队到该线程上
  • 我不确定如何从 StdAudio 库中获取进度值。如果有办法,那么可以通过其 setProgress(...) 方法来设置 SwingWorker 的进度状态。如果没有,那么您可以猜测,我想或者您最好使用不确定的进度条。我相信 JProgressBar 有一个名为 setInminateate(true) 的方法可以用于此目的。

关于java - StdAudio 类使我的 JFrame 不显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31100748/

相关文章:

Java 重绘方法不起作用,为什么?

java - 如何打印自定义纸张尺寸(支票 8"x 4")?

java - 释放驻留在字符串池中的对象的字符串类型

java - 默认异常处理程序显式处理异常的首选方法是什么?

java - java中堆内存和字符串常量池有什么区别

c - 如何在运行时更改宏定义

c - x86 gcc sleep block 或自旋?

java - 绕 z 轴旋转的漂移

java多线程应用程序更新数据库

java - 跟踪 Swing GUI "current state"