5

Javaアプリケーションからmp3ファイルを再生するための本当に簡単な方法が欲しかったのです。調べてみると、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スレッドで動作するのを何度も見てきました(悲しいことに、プログラムからの正常な終了を可能にする実際の問題があります)。

そのため、コードを独自のスレッドに配置し、そのスレッドが終了したときにプログラムのメインスレッドを終了すれば、問題はないと思いました。(これは完全に説得力のある考えではないことがわかりましたが、とにかく、試してみようと思いました。)そこで、次の2番目のバージョンのコードを作成しました。

メインスレッドは次のとおりです。

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

}

そして、実際にmp3ファイルを再生する必要があるMsgスレッドのコードは次のとおりです。

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スレッドを離れる」と表示されます。次に「Here。」です。これは、ご覧のとおり、それぞれ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()呼び出しを削除しました。これでオーディオクリップが再生されましたが、プログラムは再び終了しませんでした。

うーん!

これを優雅に機能させる方法について、それが機能したいと思うような明白な方法で何かアイデアはありますか?クリップを再生するために電話をかけたいだけで、プログラムを終了できるようにしたいと思います。

前もって感謝します!

4

2 に答える 2

7

最初のprogtestクラスでは、ウィンドウを作成しないため、最後のウィンドウを閉じるときのimplicitExitアクションは呼び出されません。これは、アプリケーションのexitメソッドを呼び出すまでプログラムが実行され続けることを意味しますが、これは実行しません。

mp3の再生が終了した後にプログラムを終了するには、mediaPlayer.setOnEndOfMedia(runnable)を呼び出し、runnableコールバックでPlatform.exit()メソッドを呼び出します。

medplMsg.setOnEndOfMedia(new Runnable() {
  @Override public void run() {
    Platform.exit();
  }
});

あなたの質問の他のすべてのスレッドのものは必要ありません(そしてとにかくあなたの問題を解決しません...)。本当に必要でない限り、カスタムスレッドを使用することはお勧めしません(必要ありません)。

JavaFX 2.2は、次のAPIを追加します。

Platform.setImplicitExit(boolean implicitExit)

implicitExit属性を指定された値に設定します。この属性がtrueの場合、JavaFXランタイムは、最後のウィンドウが閉じられたときに暗黙的にシャットダウンします。JavaFXランチャーはApplication.stop()メソッドを呼び出し、JavaFXアプリケーションスレッドを終了します。この属性がfalseの場合、アプリケーションは、最後のウィンドウが閉じられた後でも、アプリケーションがexit()を呼び出すまで、正常に実行され続けます。デフォルト値はtrueです。

これはあなたが抱えている問題についてあなたにいくつかの手がかりを与えるはずです。

于 2012-06-05T21:51:30.707 に答える
0

私自身の質問に対するこの答えは、このスレッドと私の元の投稿で参照している他のスレッドでのjewelseaの優れた応答から生じる問題を最終的に解決したコードの決定的な例を示すことです。

さて、次のコードが機能しました(そして、jewelseaは、スレッドが不要であり、ここのポイントの横にあるとコメントしていました):

import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;

public class progtest6 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.setOnEndOfMedia(new Runnable() {
            @Override
            public void run()
            {
                Platform.exit();
            }
        });
        medplMsg.play();

        System.out.println("Here.\n");

    } /* END:  start() */

}

ジュエルシーありがとうございます。

于 2012-06-05T22:52:13.057 に答える