2012-06-05 37 views
5

Tôi muốn một cách thực sự đơn giản để phát một tệp mp3 từ một ứng dụng Java. Sau khi một số nghiên cứu tôi thấy rằng các phiên bản mới nhất của Java 7 SE được đóng gói với JavaFX, vì vậy tôi nghĩ rằng tôi sẽ cố gắng. Câu hỏi này KHÔNG phải là về việc phát các tệp mp3, nhưng về việc làm cho JavaFX hoạt động theo cách được xử lý tốt.JavaFX 2.1 và chủ đề? - hay - Kết thúc một ứng dụng JavaFX một cách duyên dáng?

Vì vậy, trong thí nghiệm đầu tiên của tôi với JavaFX, tôi đã sử dụng một số mã gợi ý trong một bài đăng để stackoverflow (see here) và tạo ra, về cơ bản, các chương trình thử nghiệm sau đây:

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

} 

(Đây là một chút phức tạp hơn chương trình thử nghiệm ban đầu của tôi: phiên bản này đến về sau lời đề nghị từ jewelsea làm để đáp ứng với một câu hỏi trước đó tôi đã đăng về việc chương trình chạy ở tất cả (see here))

để biên dịch mã này tôi đã sử dụng:.

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

Và, để chạy mã tôi đã đi vào tôi .. \ thư mục bin và sử dụng:

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

Chương trình này chạy và đóng các vở kịch clip. Tuy nhiên, chương trình không trở lại dấu nhắc lệnh trừ khi tôi làm một Ctrl-C.

Hành vi đó dường như giống như một số vấn đề về chuỗi. Tôi đã thấy loại hành vi này nhiều lần làm việc với các chủ đề Java (trong đó, thật đáng buồn, có vấn đề thực sự cho phép thoát khỏi các chương trình duyên dáng). Vì vậy, tôi nghĩ, có lẽ nếu tôi đặt mã trong chủ đề riêng của nó và sau đó kết thúc chủ đề chính của chương trình khi chủ đề đó kết thúc, mọi thứ sẽ ổn thôi. (Tôi có thể thấy rằng đây không phải là hoàn toàn một ý nghĩ chắc chắn, nhưng dù sao, tôi nghĩ rằng tôi sẽ cố gắng.) Vì vậy, tôi đã viết phiên bản thứ hai sau của mã:

Dưới đây là các chủ đề chính:

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

} 

và đây là mã cho thread Msg mà thực sự nên chơi các tập tin 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() */ 

} 

(tôi đã xây dựng và chạy những file này với cùng một lệnh (với những sửa đổi lại tên file và classnames) như trên.)

Chương trình chạy và phát tệp mp3. Trước khi bạn nghe tệp, bạn sẽ thấy "Rời khỏi chuỗi chủ đề". và sau đó "Ở đây", mà như bạn có thể thấy đến từ sợi Msg và chủ đề chính tương ứng. Nhưng, một lần nữa, chương trình không kết thúc. Tôi phải nhấn Ctrl-C để trở về dấu nhắc lệnh.

Tôi đặt một cuộc gọi System.exit() ngay tại cuối của chuỗi chính ở đó để xem hành vi sẽ là gì. Hành vi là clip không được nghe thấy. Dường như cuộc gọi System.exit() đã kết thúc quá trình trước khi clip được phát.

Vì vậy, tiếp theo tôi đã thử đặt các dòng sau vào giữa System.out.println ("Đây. \ N"); và System.exit() gọi tôi thực hiện:.

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

(KeyIO là một lớp I thực hiện chỉ để làm đầu ra đầu vào bàn phím đơn giản Các chi tiết không thực sự liên quan ở đây.)

Tôi nhận thấy rằng điều này sẽ chỉ đơn giản là chặn chuỗi chính từ trước cho đến khi clip được phát.

Nhưng, không. Thay vào đó, clip không phát. Khi tôi nhấn ENTER, chương trình đã thoát mà không phát clip.

OK, vì vậy bây giờ tôi đã để lại mã chặn nhập bằng bàn phím, nhưng tôi đã thực hiện cuộc gọi System.exit(). Bây giờ clip âm thanh đã phát, nhưng chương trình không kết thúc lại.

Urgh!

Bất kỳ ý tưởng nào để có được điều này một cách duyên dáng để hoạt động theo cách rõ ràng để nó hoạt động? Tôi chỉ muốn gọi điện để phát clip, và sau đó tôi muốn có thể kết thúc chương trình.

Cảm ơn bạn trước!

Trả lời

8

Trong lớp progtest đầu tiên, bạn không tạo cửa sổ, vì vậy hành động implicitExit khi đóng cửa sổ cuối cùng không được gọi. Điều này có nghĩa là chương trình sẽ tiếp tục chạy cho đến khi bạn gọi phương thức thoát của ứng dụng mà bạn không làm.

Để chương trình thoát sau khi mp3 của bạn phát xong, hãy gọi mediaPlayer.setOnEndOfMedia(runnable) và trong cuộc gọi lại runnable gọi phương thức Platform.exit().

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

Mọi thứ khác trong câu hỏi của bạn không bắt buộc (và không giải quyết vấn đề của bạn ...). Tôi sẽ không khuyên bạn nên sử dụng luồng tùy chỉnh trừ khi bạn thực sự cần nó (mà bạn không).

JavaFX 2.2 thêm api sau:

Platform.setImplicitExit(boolean implicitExit) 

Thiết lập thuộc tính implicitExit với giá trị quy định. Nếu thuộc tính này là đúng, thời gian chạy JavaFX sẽ tắt hoàn toàn khi cửa sổ cuối cùng bị đóng; trình khởi chạy JavaFX sẽ gọi phương thức Application.stop() và chấm dứt chuỗi ứng dụng JavaFX. Nếu thuộc tính này là sai, ứng dụng sẽ tiếp tục chạy bình thường ngay cả sau khi cửa sổ cuối cùng bị đóng, cho đến khi ứng dụng gọi thoát(). Giá trị mặc định là true.

Điều này sẽ cung cấp cho bạn một số đầu mối về các vấn đề bạn đang gặp phải.

+0

Tuyệt vời! Nó hoạt động như một say mê. Tôi sẽ đăng toàn bộ mã bên dưới. Cảm ơn bạn jewelsea !!! Rất hữu ích. Và nó đã cho tôi rất nhiều cái nhìn sâu sắc về cách tôi có thể tìm ra một số thứ này trong tương lai. Cảm ơn bạn. –

0

Câu trả lời này cho câu hỏi của riêng tôi là đưa ra một ví dụ dứt khoát về mã giải quyết vấn đề xuất phát từ các câu trả lời tuyệt vời của jewelsea trong chủ đề này và câu trả lời khác trong bài viết gốc của tôi.

Được rồi, vì vậy đoạn mã sau làm việc (và jewelsea đã đúng trong bình luận rằng luồng là không cần thiết và bên cạnh bất kỳ điểm nào ở đây):

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

} 

Cảm ơn bạn jewelsea.

Các vấn đề liên quan