JavaFX 2.1 и потоки? -или- Изящное завершение приложения JavaFX?

Мне нужен был очень простой способ воспроизведения mp3-файла из Java-приложения. После некоторых исследований я обнаружил, что новейшие версии Java 7 SE упакованы с JavaFX, поэтому я решил попробовать. Этот вопрос НЕ о воспроизведении mp3-файлов, а о том, чтобы заставить JavaFX работать правильно.

Итак, в своем первом эксперименте с JavaFX я использовал некоторый код, предложенный в посте на stackoverflow ( см. здесь), и создал, по сути, следующую тестовую программу:

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() */

}

(Это немного больше сложнее, чем моя первоначальная тестовая программа: эта версия появилась после предложений отjewelsea, сделанных в ответ на ранее опубликованный мною вопрос о том, как заставить программу вообще работать (см. здесь).)

Чтобы скомпилировать этот код Я использовал:

javac -cp "c:\Program Files\Oracle\JavaFX 2.1 Runtime\lib\jfxrt.jar";..\bin -d ..\bin ..\src\progtest.java

И, чтобы запустить код, я зашел в свой каталог ..\bin и использовал:

java -cp .;"c:\Program Files\Oracle\JavaFX 2.1 Runtime\lib\jfxrt.jar" progtest

Эта программа запускается и воспроизводит воспроизведение клипа. Однако программа не возвращается в командную строку, пока я не нажму Ctrl-C.

Такое поведение похоже на какую-то проблему с потоком. Я много раз наблюдал такое поведение, работая с потоками Java (у которых, к сожалению, есть реальные проблемы, позволяющие изящно выходить из программ).

Итак, я подумал, что, возможно, если я помещу код в отдельный поток, а затем завершу основной поток программы, когда этот поток завершится, все будет в порядке.(Я мог видеть, что это не совсем убедительная мысль, но в любом случае я решил попробовать.) Итак, я написал следующую вторую версию кода:

Вот основной поток:

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() */

}

А вот это код для потока Msg, который должен воспроизводить 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() */

}

(я создал и запустил эти файлы с помощью той же команды (с соответствующими изменениями в отношении имен файлов и имен классов), что и выше).

Программа запускается и воспроизводится. файл mp3. Прежде чем вы услышите файл, вы увидите сообщение «Выход из цепочки сообщений». а затем «Здесь», которые, как вы можете видеть, исходят из потока Msg и основного потока соответственно. Но, опять же, программа не заканчивается. Мне нужно нажать Ctrl-C, чтобы вернуться в командную строку.

Я поместил вызов System.exit() прямо в конец основного потока, просто чтобы посмотреть, каким будет поведение. Поведение заключалось в том, что клип не был слышен. Казалось, что вызов System.exit() завершил процесс до того, как клип был воспроизведен.

Затем я попытался вставить следующие строки между System.out.println("Here.\n"); и вызов System.exit(), который я сделал:

System.out.print("Press ENTER to end...");
KeyIO.ReadLine();

(KeyIO — это класс, который я создал просто для вывода ввода с клавиатуры. Подробности здесь не очень важны.)

Я полагал, что это просто заблокирует основной нить от продвижения вперед до воспроизведения клипа.

Но нет. Вместо этого клип не воспроизводился. Когда я нажал ENTER, программа завершилась без воспроизведения клипа.

Итак, теперь я оставил код блокировки ввода с клавиатуры, но убрал вызов System.exit(). Теперь аудиоклип воспроизводился, но программа снова не закончилась.

Ура!

Есть идеи, как изящно заставить это работать таким образом, чтобы было очевидно, что хотелось бы, чтобы это работало? Я просто хочу позвонить, чтобы воспроизвести клип, а затем я хочу иметь возможность завершить программу.

Заранее спасибо!

5
задан rgettman 16 February 2018 в 00:08
поделиться