2016-10-07 1 views
0

Hallo, ich versuche gerade, Musik zu meiner Anwendung hinzuzufügen und jetzt habe ich das Programm die Dateinamen aus einer Datei zu bekommen und spielen sie. Aufgrund eines Fehlers in der Anwendung, die ich versucht habe zu vermitteln, indem ich den Thread in den Ruhezustand versetzt habe, spielt der Musik-Player beide Stücke zur gleichen Zeit, was zwar gut klingt, aber mir nicht hilft. Unten ist mein Code:Musik-Player liest aus Textdatei spielt alle Stücke auf einmal Javafx

public static class MusicPlayerService extends Service<Void> 
{ 
    public static File[] musicArray = new File[2]; 
    public static int fileNumber = 0; 

    @Override 
    protected Task<Void> createTask(){ 
     Scanner musicListReader; 
     try { 
      musicListReader = new Scanner(new File("Music_PlayList.txt")); 
      while(musicListReader.hasNext()) 
      { 
       musicArray[fileNumber] = new File(musicListReader.next()); 
       String uriString = musicArray[fileNumber].toURI().toString(); 
       Media media = new Media(uriString); 
       MediaPlayer player = new MediaPlayer(media); 
       player.play(); 
       Thread.sleep((long) media.getDuration().toMillis()); 
       fileNumber++; 
      } 
     } catch (FileNotFoundException | InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     return null; 
    } 
} 
+0

was 'media.getDuration() toMillis()' Rückkehr? –

+0

Und da ist mein Problem. Anscheinend gibt es NaN statt einer Zahl zurück. Was würde das sein? Null? Und wenn ja, gibt es einen anderen Weg, den Wert zu bekommen? –

+0

Es ist nicht null, es ist 'NaN'. Siehe [Dokumente] (http://docs.oracle.com/javase/8/javafx/api/javafx/util/Duration.html#toMillis--). Sie versuchen, auf die Dauer zuzugreifen, bevor das Medium sie gelesen hat (sie ist offensichtlich in die Metadaten der Audiodatei eingebettet). Die schlafende Schleife ist wahrscheinlich nicht wirklich ein guter Ansatz: Warum registrieren Sie nicht einen 'onStopped'-Handler mit dem Player und spielen den nächsten Track, wenn es einen anderen gibt. –

Antwort

1

Anstelle des Looping-and-Sleeping-Ansatzes sollten Sie stattdessen einen ereignisgesteuerten Ansatz verwenden. Sie können einen Handler onStopped mit dem Media Player registrieren und den nächsten Song (falls es einen nächsten Song gibt) von dort aus starten. Auf diese Weise müssen Sie auch keinen Hintergrund-Thread verwenden.

Etwas wie:.

Queue<File> musicList = new LinkedList<File>(); 

try (Scanner musicListReader = new Scanner(new File("Music_PlayList.txt"))) { 

    while (musicListReader.hasNext()) { 
     musicList.add(new File(musicListReader.next())); 
    } 

} catch (Exception e) { 
    e.printStackTrace(); 
} 

playNextMusicFile(musicList); 

// ... 

private void playNextMusicFile(Queue<File> musicList) { 
    if (musicList.isEmpty()) { 
     return ; 
    } 

    Media media = new Media(musicList.remove().toURI().toString()); 
    MediaPlayer player = new MediaPlayer(media); 
    player.setOnEndOfMedia(() -> { 
     player.dispose(); 
     playNextMusicFile(musicList); 
    }); 
    player.play(); 
} 
+0

Ich frage mich nur, ob es einen Grund gibt, warum du geschrieben hast "Auf diese Weise brauchst du auch keinen Hintergrund-Thread." Ist es schädlich, es in einem Hintergrundthread zu haben oder ist es nur so, dass ich 'Platform.runLater()' nicht verwenden muss, wenn ich mit der Schnittstelle interagiere? –

+0

@AdamRen Es ist einfacher (also weniger anfällig für subtile Fehler). Es ist immer besser, Multithreading zu vermeiden, wenn es möglich ist, da es sehr schwierig ist, richtig zu arbeiten. Threads sind auch ziemlich teuer, was die Systemressourcen anbelangt - es gibt eine begrenzte Anzahl, die Sie jederzeit zuweisen können, obwohl das hier kein Problem wäre. –

+0

Das scheint Grund genug zu sein. Was ist der maximale Thread, weil, während ich die Anwendung fortfahre, ich noch einige davon verwenden werde? –

Verwandte Themen