音乐播放时JFrame没有显示?

时间:2013-06-12 01:59:02

标签: java swing audio concurrency event-dispatch-thread

我正在使用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();
        }
    } 

}

2 个答案:

答案 0 :(得分:3)

这表示您正在阻止事件调度线程。这将阻止在您停止阻止之前更新任何UI元素。

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

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

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

请查看Concurrency in 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();
            }
        }
    }
}

答案 1 :(得分:2)

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