简体   繁体   English

音乐播放时JFrame不显示吗?

[英]JFrame doesn't show when music is playing?

I am using the mp3plugin.jar library and my music works great. 我正在使用mp3plugin.jar库,我的音乐效果很好。 The only problem is that when my program starts the JFrame doesn't show. 唯一的问题是,当我的程序启动时,JFrame不会显示。 Before I added the music, it worked perfectly. 在添加音乐之前,它运转良好。 This is my code for the music: 这是我的音乐代码:

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

}

This suggest that you are blocking the Event Dispatching Thread. 这表明您正在阻止事件调度线程。 This will prevent any UI elements from being updated until you stop blocking. 这将防止在停止阻止之前更新任何UI元素。

Having only looked at you code, I would suggest that your culprit is here... 只看了您的代码,我建议您的罪魁祸首在这里...

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

Try creating a background thread in which you either run the Music class in OR run the loop within it's own background thread. 尝试创建一个后台线程,您可以在其中运行Music类或在其自己的后台线程中运行循环。

Take a look at Concurrency in Swing for more details 查看Swing中的并发以了解更多详细信息

Updated with working example 更新了工作示例

This is a rather crude example. 这是一个很粗糙的例子。 Normally I would have a single Thread which would be responsible for playing the music, but which could be interrupted and made to play another song, but this is just a proof of concept. 通常,我只有一个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();
            }
        }
    }
}

This is a classic example of blocking the Swing event dispatch thread with a long-running bit of code. 这是一个用长时间运行的代码阻塞Swing事件分配线程的经典示例。 This will cause the GUI to freeze since the thread isn't available to paint components or interact with the user. 由于线程不可用于绘制组件或与用户交互,因此这将导致GUI冻结。 The solution: use a background thread for the music so you don't block the GUI's event thread. 解决方案:对音乐使用背景线程,这样就不会阻塞GUI的事件线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM