我有一个有效的java程序,一个简单的mp3播放器。
一切正常,可以跳过轨道等......但经过几次跳过(特别是后退按钮(上一首曲目),我总是得到一个IllegalThreadStateException
。我不熟悉线程,所以我是不知道该怎么做。
这是一个学校作业,MP3课程已经发给我们。 (不能修改)
任何提示将不胜感激!谢谢!
MP3类(无法修改):
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import javazoom.jl.player.Player;
public class MP3 extends Thread {
private final File mp3_file;
private Player player;
public MP3(String mp3_path) {
mp3_file = new File(mp3_path);
}
public MP3(File mp3) {
mp3_file = mp3;
}
public void play() {
try {
FileInputStream fis = new FileInputStream(mp3_file);
BufferedInputStream bis = new BufferedInputStream(fis);
player = new Player(bis);
}
catch (Exception e) {
System.out.println("Problem playing file " + mp3_file);
System.out.println(e);
}
// run in new thread to play in background
start(); // Instructs JVM to call run() in separate thread
}
public boolean isPlaying() {
if (player == null)
return false;
else {
return !player.isComplete();
}
}
public void run() {
try { player.play(); }
catch (Exception e) { System.out.println(e); }
}
public void quit() {
if (player != null) {
player.close();
player = null;
}
}
public String toString() {
return mp3_file.toString();
}
}
我的代码:
import javax.swing.*;
public class MP3Random extends JFrame {
private JPanel backgroundPanel;
private PlaylistPanel playlistPanel;
private MainPanel mainPanel;
int trackTime;
private MP3 current;
private ButtonListener buttonListener;
private TimerListener timerListener;
private Timer timer;
private boolean playButtonStatus;
public MP3Random() {
buttonListener = new ButtonListener();
timerListener = new TimerListener();
backgroundPanel = new JPanel();
mainPanel = new MainPanel();
playlistPanel = new PlaylistPanel();
timer = new Timer(1000, timerListener);
timer.setInitialDelay(0);
playButtonStatus = false;
setMinimumSize(new Dimension(650, 400));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout(0, 0));
backgroundPanel.setLayout(new BorderLayout(0, 0));
backgroundPanel.setBorder(null);
backgroundPanel.add(playlistPanel, BorderLayout.CENTER);
backgroundPanel.add(mainPanel, BorderLayout.NORTH);
getContentPane().add(backgroundPanel);
setVisible(true);
}
private void playSong(MP3 current) {
ImageIcon stopIcon = new ImageIcon(MP3Random.class.getResource("/pa2/icons/stop.png"));
playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current));
mainPanel.playButton.setIcon(stopIcon);
trackTime = 0;
current.play();
timer.restart();
mainPanel.trackTitleLabel.setText(getTrackTitle(current.toString()));
}
private void stopPlayback() {
try {
current.quit();
timer.stop();
playButtonStatus = false;
mainPanel.trackTitleLabel.setText("");
mainPanel.trackTimeLabel.setText("");
mainPanel.playButton.setIcon(mainPanel.playIcon);
}
catch (Exception e) {};
}
private String getTrackTitle (String filename) {
return filename.substring(filename.lastIndexOf('/')+1, filename.lastIndexOf(".mp3"));
}
private String formatTime(int durationInSeconds) {
int minutes = durationInSeconds / 60;
int seconds = durationInSeconds % 60;
return ( (minutes < 10 ? "0" : "") + minutes
+ ":" + (seconds< 10 ? "0" : "") + seconds );
}
//Panel containing track display/time, media control buttons
private class MainPanel extends JPanel {...}
//Panel containing JList and add/remove from playlist buttons
private class PlaylistPanel extends JPanel {...}
private class ButtonListener implements ActionListener {
File[] filesSelected;
MP3[] mp3List;
Random generator = new Random();
public void actionPerformed (ActionEvent event) {
if (event.getSource() == playlistPanel.addButton) {
playlistPanel.fileChooser = new JFileChooser();
playlistPanel.fileChooser.setMultiSelectionEnabled(true);
//FileFilter only allows *.mp3
playlistPanel.fileChooser.setAcceptAllFileFilterUsed(false);
playlistPanel.fileChooser.setFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = f.toString().substring(f.toString().lastIndexOf('.')+1);
if (extension != null) {
if (extension.equals("mp3"))
return true;
else
return false;
}
return false;
}
public String getDescription() {
return "*.mp3";
}
});
if (playlistPanel.fileChooser.showOpenDialog(MP3Random.this) == JFileChooser.APPROVE_OPTION) {
filesSelected = playlistPanel.fileChooser.getSelectedFiles();
mp3List = new MP3[filesSelected.length];
mainPanel.playButton.setEnabled(true);
playlistPanel.removeButton.setEnabled(true);
//more than 1 file selected
if (mp3List.length > 1) {
mainPanel.shuffleButton.setEnabled(true);
mainPanel.nextButton.setEnabled(true);
}
for (int i = 0; i < mp3List.length; i++)
playlistPanel.listModel.addElement(mp3List[i] = new MP3(filesSelected[i]));
current = (MP3) playlistPanel.listModel.get(0);
playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current));
}
}
//remove button
if (event.getSource() == playlistPanel.removeButton) {
Object[] temp = playlistPanel.playList.getSelectedValues();
for (Object f : temp) {
playlistPanel.listModel.removeElement(f);
}
//1 song in list
if (playlistPanel.listModel.getSize() == 1) {
mainPanel.backButton.setEnabled(false);
mainPanel.nextButton.setEnabled(false);
mainPanel. shuffleButton.setEnabled(false);
}
//no songs in list
if (playlistPanel.listModel.getSize() == 0) {
playlistPanel.removeButton.setEnabled(false);
mainPanel.playButton.setEnabled(false);
mainPanel.backButton.setEnabled(false);
mainPanel.nextButton.setEnabled(false);
mainPanel.shuffleButton.setEnabled(false);
current = null;
}
}
//play button
if (event.getSource() == mainPanel.playButton) {
//if song not playing
if (!playButtonStatus) {
if (!playlistPanel.playList.isSelectedIndex(playlistPanel.listModel.indexOf(current)))
current = (MP3) playlistPanel.playList.getSelectedValue();
playSong(current);
playButtonStatus = true;
}
//if song is playing
else
stopPlayback();
}
//next button
if (event.getSource() == mainPanel.nextButton) {
if (!mainPanel.backButton.isEnabled())
mainPanel.backButton.setEnabled(true);
if (current.isPlaying()) {
current.quit();
current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)+1);
playSong(current);
}
else {
current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)+1);
playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current));
}
if (playlistPanel.listModel.indexOf(current) == playlistPanel.listModel.size() - 1)
mainPanel.nextButton.setEnabled(false);
}
//back button
if (event.getSource() == mainPanel.backButton) {
if (!mainPanel.nextButton.isEnabled())
mainPanel.nextButton.setEnabled(true);
if (current.isPlaying()) {
current.quit();
current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)-1);
playSong(current);
}
else {
current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)-1);
playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current));
}
if (playlistPanel.listModel.indexOf(current) == 0)
mainPanel.backButton.setEnabled(false);
}
//shuffle jlist
if (event.getSource() == mainPanel.shuffleButton) {
if (playlistPanel.listModel.size() > 1) {
int n = playlistPanel.listModel.getSize();
while (n > 1) {
int k = generator.nextInt(n);
n--;
MP3 tempMP3 = (MP3) playlistPanel.listModel.elementAt(n);
playlistPanel.listModel.set(n,playlistPanel.listModel.elementAt(k));
playlistPanel.listModel.set(k, tempMP3);
current = (MP3) playlistPanel.listModel.get(0);
playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current));
}
}
}
}
}
private class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
if (playlistPanel.listModel.indexOf(current) > 0)
mainPanel.backButton.setEnabled(true);
if (playlistPanel.listModel.indexOf(current) == playlistPanel.listModel.size()-1)
mainPanel.nextButton.setEnabled(false);
if (!current.isPlaying()) {
if (playlistPanel.listModel.size() > 1 && playlistPanel.listModel.indexOf(current) < playlistPanel.listModel.size()-1) {
current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)+1);
playSong(current);
}
else
stopPlayback();
}
else {
mainPanel.trackTimeLabel.setText(formatTime(trackTime));
trackTime++;
}
}
}
public static void main(String[] args) throws Exception {
MP3Random instance = new MP3Random();
}
}
错误:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:656)
at pa2.MP3.play(MP3.java:41)
at pa2.MP3Random.playSong(MP3Random.java:68)
at pa2.MP3Random.access$4(MP3Random.java:62)
at pa2.MP3Random$ButtonListener.actionPerformed(MP3Random.java:373)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2028)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2351)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6373)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6138)
at java.awt.Container.processEvent(Container.java:2085)
at java.awt.Component.dispatchEventImpl(Component.java:4735)
at java.awt.Container.dispatchEventImpl(Container.java:2143)
at java.awt.Component.dispatchEvent(Component.java:4565)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4621)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4282)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4212)
at java.awt.Container.dispatchEventImpl(Container.java:2129)
at java.awt.window.dispatchEventImpl(window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4565)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:679)
at java.awt.EventQueue.access$000(EventQueue.java:85)
at java.awt.EventQueue$1.run(EventQueue.java:638)
at java.awt.EventQueue$1.run(EventQueue.java:636)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
at java.awt.EventQueue$2.run(EventQueue.java:652)
at java.awt.EventQueue$2.run(EventQueue.java:650)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:649)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
答案 0 :(得分:8)
问题在于:
public void play() {
try {
FileInputStream fis = new FileInputStream(mp3_file);
BufferedInputStream bis = new BufferedInputStream(fis);
player = new Player(bis);
}
catch (Exception e) {
System.out.println("Problem playing file " + mp3_file);
System.out.println(e);
}
// run in new thread to play in background
start(); // <======== PROBLEM
}
Thread.Start
java doc说:
抛出:IllegalThreadStateException - 如果线程已经存在 启动。
基本上,一个线程不能多次启动。只要您在已Play
已启动的MP3
实例上致电MP3.Play()
,您就会收到此异常
我建议的是在调用MP3.Play
时创建一个新线程来播放你的音轨。
玩家类看起来像:
public class MP3Player extends Thread {
public void PlayFile(String soundFile){
//... Add player logic here
}
public void StopPlaying(){
//.. Stop playing and gracefully exit this thread
}
}
在MP3课程中:
public class MP3{
MP3Player currentPlayer = null;
// ...
public void play() {
if(currentPlayer != null) currentPlayer.StopPlaying();
currentPlayer = new MP3Player();
currentPlayer.PlayFile(mp3_file);
}
}
答案 1 :(得分:4)
首先,您需要熟悉Threads,因为您正在使用的项目使用它们!您的课程教材可能涵盖此主题。仔细阅读。线程非常重要。如果您的教科书不清楚,您还可以read the official Java tutorial 。
回到你的问题。 MP3类的每个实例都在一个单独的Thread中运行。 MP3线程与主程序执行(即运行main方法的线程)分开,并且swing UI也在单独的线程中运行。
您的错误表明引用java.lang.IllegalThreadStateException
的Javadoc:
线程未处于所请求操作的适当状态。 例如,请参阅Thread。类中的suspend和resume方法。
以下是一些要注意的事项:
我的答案中的第2点可能与您的问题无关 - 在使用Threads时理解这一点非常重要。例如,如果要在PlaylistPanel中更改可用歌曲列表(多个线程可以更改它),那么您需要使该类的一部分同步。如果另一个线程正在运行同步方法,则强制线程等待。您的问题是尝试重新启动“已死”的线程查看JavaDocs for Thread:
不止一次启动线程永远不合法。特别是,a 一旦完成执行,线程可能无法重新启动。
所以要启动该线程,请调用start。开始通话。该线程现在将与其他线程同时“运行”,直到run()终止。一旦它终止,我们就完成了这个线程。如果我们想要相同的线程播放多首歌曲,我们需要实现此行为。但是你发布的run方法(我认为你没有写;它是作为这个任务的一部分给出的)非常简单。它调用player.play();
,当palay终止时,线程完成。
我认为run()方法的最后一行应该是player = null
,这样isPlaying()方法才能正常工作。
答案 2 :(得分:2)
只是一个猜测,但是:可能是,你在线程中调用AWT-Widgets上的方法?对于SWT,这不起作用,例如,必须从GUI-Thread调用widget调用,即创建它们的线程。 不确定AWT是否相同,但值得检查...