Chciałam naprawdę prosty sposób na odtwarzanie pliku mp3 z aplikacji Java. Po kilku badaniach odkryłem, że najnowsze wersje Java 7 SE są pakowane z JavaFX, więc pomyślałem, że spróbuję. To pytanie NIE dotyczy odtwarzania plików mp3, ale o tym, aby JavaFX działał w dobrze zachowany sposób.JavaFX 2.1 i wątki? -lub- Kończenie aplikacji JavaFX z gracją?
Tak, w moim pierwszym eksperymencie z JavaFX, kiedyś jakiś kod zasugerował we wpisie do stackoverflow (see here) i utworzoną zasadniczo następujący program testowy:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
public class progtest extends Application
{
/*---------------------------------------------------------*\
FUNCTION: main()
\*---------------------------------------------------------*/
public static void main(String args[])
{
launch(args);
} /* END: main() */
/*---------------------------------------------------------*\
FUNCTION: start()
\*---------------------------------------------------------*/
@Override
public void start(Stage stage)
{
Media medMsg
=
new Media(getClass().getResource("msg.mp3").toExternalForm());
MediaPlayer medplMsg = new MediaPlayer(medMsg);
medplMsg.play();
System.out.println("Here.\n");
} /* END: start() */
}
(jest to nieco bardziej skomplikowane niż mój oryginalny program testowy: wersja ta powstała po sugestii jewelsea dokonanych w odpowiedzi na wcześniejsze pytanie napisałem o uzyskanie program działa na wszystkich (see here))
Aby skompilować ten kod użyłem.
javac -cp "c:\Program Files\Oracle\JavaFX 2.1 Runtime\lib\jfxrt.jar";..\bin -d ..\bin ..\src\progtest.java
A, aby uruchomić kod poszedłem do mojego .. \ bin i używany:
java -cp .;"c:\Program Files\Oracle\JavaFX 2.1 Runtime\lib\jfxrt.jar" progtest
Ten program działa i odtwarza odtworzenia klipu. Jednak program nie powróci do wiersza polecenia, chyba że zrobię Ctrl-C.
To zachowanie wydawało się być kwestią wątku. Widziałem takie zachowanie wiele razy pracując z wątkami Java (które, niestety, mają prawdziwe problemy pozwalające na pełne wdzięku wyjścia z programów).
Pomyślałem więc, że być może, jeśli ustawię kod we własnym wątku, a następnie zakończę główny wątek programu, gdy skończy się ten wątek, wszystko będzie dobrze. (Widziałem, że nie było to całkowicie spójne myśli, ale mimo to, myślałem, że chciałbym spróbować.) Więc napisałem następujący drugą wersję kodu:
Oto główny wątek:
import javafx.application.Application;
import javafx.stage.Stage;
import Msg.*;
public class progtest2 extends Application
{
/*---------------------------------------------------------*\
FUNCTION: main()
\*---------------------------------------------------------*/
public static void main(String args[])
{
launch(args);
} /* END: main() */
/*---------------------------------------------------------*\
FUNCTION: start()
\*---------------------------------------------------------*/
@Override
public void start(Stage stage)
{
Msg msgTime = new Msg();
msgTime.passClass(getClass());
msgTime.start();
try
{
msgTime.join();
}
catch (InterruptedException e)
{
}
System.out.println("Here.\n");
} /* END: start() */
}
a oto kod do wątku Msg że powinien właściwie odtworzyć plik mP3:
package Msg;
import KeyIO.*;
import javafx.application.Application;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
public class Msg extends Thread
{
private Class classRt = null;
/*--------------------------------------------------------*\
FUNCTION: passClass()
\*--------------------------------------------------------*/
public void passClass(Class rt)
{
classRt = rt;
} /* END: passClass() */
/*--------------------------------------------------------*\
FUNCTION: run()
\*--------------------------------------------------------*/
public void run()
{
Media medMsg
= new Media(classRt.getResource("msg.mp3").toExternalForm());
MediaPlayer medplMsg = new MediaPlayer(medMsg);
medplMsg.play();
System.out.println("Leaving Msg thread.\n");
} /* END: run() */
}
(i zbudował i prowadził te pliki z tego samego polecenia (mutatis mutandis ponownie nazwy plików i classnames) jak powyżej.)
Program uruchamia i odtwarza plik mp3. Zanim usłyszysz plik, zobaczysz komunikat "Pozostawienie wątku Msg". a następnie "Tutaj", które jak widać, pochodzą odpowiednio z wątku Msg i głównego wątku. Ale znowu program się nie kończy. Muszę nacisnąć Ctrl-C, aby powrócić do wiersza poleceń.
Umieściłem wywołanie System.exit() na samym końcu głównego wątku, żeby zobaczyć, jakie będzie zachowanie. Zachowanie polegało na tym, że klip nie był słyszalny. Wyglądało na to, że wywołanie System.exit() zakończyło proces przed odtworzeniem klipu.
Następnie próbowałem umieścić następujące linie pomiędzy System.out.println ("Tutaj. \ N"); a System.exit() zadzwonić zrobiłem.
System.out.print("Press ENTER to end...");
KeyIO.ReadLine();
(KeyIO jest klasa I tworzył dla robią wyjście sygnału wejściowego klawiatury prostu Szczegóły nie są naprawdę istotne tutaj.)
Pomyślałem, że to po prostu zablokuje główny wątek od przejścia do następnego klipu.
Ale nie. Zamiast tego klip nie został odtworzony. Po naciśnięciu klawisza ENTER program zakończył się bez odtwarzania klipu.
OK, więc teraz zostawiłem kod blokujący wejście klawiatury, ale wyjąłem wywołanie System.exit(). Teraz klip audio został odtworzony, ale program się nie skończył.
Urgh!
Jakieś pomysły na to, jak z wdziękiem sprawić, by działało tak, jakby to było oczywiste? Chcę tylko zadzwonić, żeby zagrać w klip, a potem chcę mieć możliwość zakończenia programu.
Z góry dziękuję!
Doskonale! To działa jak urok. Opublikuję cały kod poniżej. Dziękuję jewelsea !!! Bardzo pomocne. Dało mi to wiele informacji na temat tego, jak samemu mogę wymyślić niektóre z tych rzeczy w przyszłości. Dziękuję Ci. –