3

I have an application written in Swing, in which I want to use JavaFX's MediaPlayer for playing audio / sound files.

This is a condensed version of the main file:

class MyApp
{
   private MyApp myApp;
   private JFrame myFrame;
   private Media media;
   private MediaPlayer mediaPlayer;
   public static void main(String[] args)
   {
      Runnable thread = new Runnable()
      {
         public void run()
         {
             myApp = new MyApp();
         }          
      };
      SwingUtilities.invokeLater(thread);
  }
  public void MyApp()
  {
    //this is called by SwingUtilities.invokeLater();

    URL url = //getting URL to a sound file stored locally//;
    media = new Media(url.toString() );
    mediaPlayer = new MediaPlayer( media );                        
    mediaPlayer.play();

    myFrame = new JFrame(); //building swing UI here
  }

This seems to work within Netbeans. However when Netbeans builds a .jar, and I try to run the .jar, I get an error log file built in the .jar directory containing some memory / threading errors.

Do I need to use the Platform.runLater() method to get this to work? Or is there anything else I'm doing wrong?

Ali
  • 261,656
  • 265
  • 575
  • 769

1 Answers1

4

When interacting with JavaFX controls embedded in Swing app, definitely do this inside a Platform.runLater call, not a Swing.invokeLater call.

You should also ensure that the JavaFX system is initialized and (preferably) that the application is ackaged using the JavaFX packaging tools as mentioned in this post: Playing audio using JavaFX MediaPlayer in a normal Java application?.

While running some code that creates some JavaFX controls off the JavaFX thread works for most controls and even some interactions with some controls seem to work off the JavaFX thread sometimes, in practice I find it's not worth the risks and potentially obscure errors or race conditions you may encounter while doing so. JavaFX is designed with a single threaded interaction model with the UI in mind, so it is best to keep it that way using tools like Platform.runLater. Same is true of Swing with it's event dispatch thread. You need to keep the threaded interactions between these two frameworks separate.

Looking at the 5 lines you have in your MyApp code in your question, I have the following recommendations.

Doesn't matter what thread this is executed on as it does not interact with any framework:

   

URL url = //getting URL to a sound file stored locally//;

Makes use of JavaFX controls do should be wrapped in Platform.runLater:

   

media = new Media(url.toString() );
mediaPlayer = new MediaPlayer( media );                        
mediaPlayer.play();

Interacts with the Swing framework, so should be wrapped in Swing.invokeLater:

   

myFrame = new JFrame(); //building swing UI here

Note: just one runLater for the call is not enough, you also need to invokeLater the Swing jframe call from inside the runLater body after the MediaPlayer play call.

Community
  • 1
  • 1
jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • Check the code according to the recommendations in the question and see if looks OK. The following may not be applicable to your case, but you could try creating a JavaFX project type in NetBeans and setting the main class to your Swing class (it's probably not a supported config but it seemed to work ok for me earlier today). That way Netbeans will do all your packaging automatically with the JavaFX tools and create you a JavaFX aware jar without you requiring your own build file and manifest. – jewelsea Sep 23 '12 at 05:32
  • If you continue to have issues, create a short executable example and post it, an environment description and error dump to an issue created against the runtime project at http://javafx-jira.kenai.com – jewelsea Sep 23 '12 at 05:36