0

我正在使用 mp3plugin.jar 库,我的音乐效果很好。唯一的问题是当我的程序启动时 JFrame 没有显示。在我添加音乐之前,它运行良好。这是我的音乐代码:

package com.org.pong;
import javax.sound.sampled.*;
import javax.sound.*;
import java.io.*;
import java.net.URL;

public class Music {

    Music(String url) {

        int total, totalToRead, numBytesRead, numBytesToRead;
        byte[] buffer;
        boolean stopped;
        AudioFormat wav;
        TargetDataLine line;
        SourceDataLine lineIn;
        DataLine.Info info;
        File file;
        FileInputStream fis;

        // AudioFormat(float sampleRate, int sampleSizeInBits,
        // int channels, boolean signed, boolean bigEndian)
        wav = new AudioFormat(44100, 16, 2, true, false);
        info = new DataLine.Info(SourceDataLine.class, wav);

        buffer = new byte[1024 * 333];
        numBytesToRead = 1024 * 333;
        total = 0;
        stopped = false;

        if (!AudioSystem.isLineSupported(info)) {
            System.out.print("no support for " + wav.toString());
        }
        try {
            // Obtain and open the line.
            lineIn = (SourceDataLine) AudioSystem.getLine(info);
            lineIn.open(wav);
            lineIn.start();
            fis = new FileInputStream(file = new File(url));
            totalToRead = fis.available();

            while (total < totalToRead && !stopped) {
                numBytesRead = fis.read(buffer, 0, numBytesToRead);
                if (numBytesRead == -1)
                break;
                total += numBytesRead;
                lineIn.write(buffer, 0, numBytesRead);
            }

        } catch (LineUnavailableException ex) {
            ex.printStackTrace();
        } catch (FileNotFoundException nofile) {
            nofile.printStackTrace();
        } catch (IOException io) {
            io.printStackTrace();
        }
    } 

}
4

2 回答 2

3

这表明您正在阻塞事件调度线程。这将阻止任何 UI 元素更新,直到您停止阻止。

只看了你的代码,我建议你的罪魁祸首在这里......

while (total < totalToRead && !stopped) {
    numBytesRead = fis.read(buffer, 0, numBytesToRead);
    if (numBytesRead == -1)
    break;
    total += numBytesRead;
    lineIn.write(buffer, 0, numBytesRead);
}

尝试创建一个后台线程,您可以在其中运行Music类或在它自己的后台线程中运行循环。

查看Swing 中的并发以获取更多详细信息

更新了工作示例

这是一个相当粗略的例子。通常我会有一个Thread负责播放音乐的单曲,但它可能会被打断并播放另一首歌曲,但这只是一个概念证明。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestMusic {

    public static void main(String[] args) {
        new TestMusic();
    }

    public TestMusic() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                Music.play("/play/some/music/white/boy");

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JLabel("Look Ma, no hands"));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class Music {

        public static void play(final String url) {

            new Thread(new Runnable() {

                @Override
                public void run() {
                    new Music(url);
                }
            }).start();

        }

        private int total, totalToRead, numBytesRead, numBytesToRead;
        private byte[] buffer;
        private boolean stopped;
        private AudioFormat wav;
        private TargetDataLine line;
        private SourceDataLine lineIn;
        private DataLine.Info info;
        private File file;
        private FileInputStream fis;

        public Music(String url) {


            // AudioFormat(float sampleRate, int sampleSizeInBits,
            // int channels, boolean signed, boolean bigEndian)
            wav = new AudioFormat(44100, 16, 2, true, false);
            info = new DataLine.Info(SourceDataLine.class, wav);

            buffer = new byte[1024 * 333];
            numBytesToRead = 1024 * 333;
            total = 0;
            stopped = false;

            if (!AudioSystem.isLineSupported(info)) {
                System.out.print("no support for " + wav.toString());
            }
            try {
                // Obtain and open the line.
                lineIn = (SourceDataLine) AudioSystem.getLine(info);
                lineIn.open(wav);
                lineIn.start();
                fis = new FileInputStream(file = new File(url));
                totalToRead = fis.available();

                while (total < totalToRead && !stopped) {
                    numBytesRead = fis.read(buffer, 0, numBytesToRead);
                    if (numBytesRead == -1) {
                        break;
                    }
                    total += numBytesRead;
                    lineIn.write(buffer, 0, numBytesRead);
                }

            } catch (LineUnavailableException ex) {
                ex.printStackTrace();
            } catch (FileNotFoundException nofile) {
                nofile.printStackTrace();
            } catch (IOException io) {
                io.printStackTrace();
            }
        }
    }
}
于 2013-06-12T02:01:53.707 回答
2

这是使用长时间运行的代码阻塞 Swing 事件调度线程的经典示例。这将导致 GUI 冻结,因为线程不可用于绘制组件或与用户交互。解决方案:为音乐使用后台线程,这样您就不会阻塞 GUI 的事件线程。

于 2013-06-12T02:01:39.817 回答