JavaFX

From APIDesign

(Difference between revisions)
Jump to: navigation, search
(Dispatch Threads)
Current revision (07:28, 15 July 2014) (edit) (undo)
 
(9 intermediate revisions not shown.)
Line 1: Line 1:
-
[[wikipedia:JavaFX|JavaFX]] is new, modern UI toolkit for rendering [[Java]] UIs. The idea is tempting - instead of bloated [[wikipedia:Abstract_Window_Toolkit|AWT]] and [[Swing]] on top, one can use a completely independent UI and lightweight library instead. However, as usual when offering [[AlternativeBehaviour]], the problem is [[co-existence]] - there a tons of [[Swing]] applications around and they need to migrate to [[JavaFX]] in an incremental fashion. Unless such migration is smooth, people will rather stick with what they have right now.
+
[[wikipedia:JavaFX|JavaFX]] is new, modern UI toolkit for rendering [[Java]] UIs. The idea is tempting - instead of bloated [[wikipedia:Abstract_Window_Toolkit|AWT]] with [[Swing]] on top, one can use a completely independent UI and lightweight library (which can for example be deployed to [[iOS]]) instead. However, as usual when offering [[AlternativeBehaviour]], the problem is [[co-existence]] - there are tons of [[Swing]] applications around and they need to migrate to [[JavaFX]] in an incremental fashion. Unless such migration is smooth, people will rather stick with what they have right now.
=== Dispatch Threads ===
=== Dispatch Threads ===
-
Up until today (e.g. May 2012) mixing [[Swing]] and [[JavaFX]] was not easy because each of these two systems used its own dispatch thread. Whenever one needed to operate with [[Swing]] one had to enter the dispatch thread by using {{JDK|java/awt|EventQueue}}.invokeLater({{JDK|java/lang|Runnable}}). As soon as there was a need to manipulate with [[JavaFX]] components one had to use {{FX|javafx/application|Platform}}.runLater({{JDK|java/lang|Runnable}}). As [[Java]] is not very good at this kind of [[wikipedia:Actor_model|actor]] based coding, the result was completely unreadable code full of deeply nested {{JDK|java/lang|Runnable}}s:
+
Up until today (e.g. May 2012) mixing [[Swing]] and [[JavaFX]] was not easy because each of these two systems used its own dispatch thread. Whenever one needed to operate with [[Swing]] one had to enter the dispatch thread by using {{JDK|java/awt|EventQueue}}.invokeLater({{JDK|java/lang|Runnable}}). As soon as there was a need to manipulate with [[JavaFX]] components one had to use {{FX|javafx/application|Platform}}.runLater({{JDK|java/lang|Runnable}}). As [[Java]] is not very good at this kind of [[wikipedia:Actor_model|actor]] based coding, the result was completely unreadable code full of deeply nested {{JDK|java/lang|Runnable}}s. Here is very simple example:
<source lang="java">
<source lang="java">
Line 30: Line 30:
I am proud to announce that the mutual [[Swing]] and [[JavaFX]] interoperability has been greatly simplified during May 2012. No need for massive amount of asynchronous {{JDK|java/lang|Runnable}}s! Your [[Swing]] code can directly talk to [[JavaFX]] data structures and your [[JavaFX]] code can do the same to [[Swing]] objects. This is a [http://source.apidesign.org/hg/jdk/rev/4ed8674de305 small change], but huge step forward for [[Swing]]+[[JavaFX]] interoperability!
I am proud to announce that the mutual [[Swing]] and [[JavaFX]] interoperability has been greatly simplified during May 2012. No need for massive amount of asynchronous {{JDK|java/lang|Runnable}}s! Your [[Swing]] code can directly talk to [[JavaFX]] data structures and your [[JavaFX]] code can do the same to [[Swing]] objects. This is a [http://source.apidesign.org/hg/jdk/rev/4ed8674de305 small change], but huge step forward for [[Swing]]+[[JavaFX]] interoperability!
-
The basic idea is to share the [[Swing]] and [[JavaFX]] dispatch threads. Trivial implementation would keep the ''AWT-EventQueue-X'' and just made sure one will always use {{FX|javafx/application|Platform}}.runLater to dispatch the [[Swing]] events. More advanced implementation can even eliminate the need for ''AWT-EventQueue-X'' thread completely (as the [http://source.apidesign.org/hg/jdk/rev/4ed8674de305 patch] shows). By running the event processing in the same thread, it is safe to access [[Swing]] as well as [[JavaFX]] [[API]]s directly which greatly simplifies the coding model.
+
The basic idea is to share the [[Swing]] and [[JavaFX]] dispatch threads. Trivial implementation would keep the ''AWT-EventQueue-X'' and just make sure one will always use {{FX|javafx/application|Platform}}.runLater to dispatch the [[Swing]] events. More advanced implementation can even eliminate the need for ''AWT-EventQueue-X'' thread completely (as the [http://source.apidesign.org/hg/jdk/rev/4ed8674de305 patch] shows). By running the event processing in the same thread, it is safe to access [[Swing]] as well as [[JavaFX]] [[API]]s directly which greatly simplifies the coding model.
-
I've send my patch to Artem (Oracle's [[JavaFX]] guru) as a sketch of what could be done and the news from Artem are really great. The basic interoperability seems to work fine. Originally I was slightly afraid whether processing of events in different thread will work seamlessly, but now (when it has been experimentally verified) I think the changes have always been high for this system to work well.
+
I've send my patch to Artem (Oracle's [[JavaFX]] guru) as a sketch of what could be done and the news from Artem are really great. The basic interoperability seems to work fine. Originally I was slightly afraid whether processing of events in different thread will work seamlessly, but now (when it has been experimentally verified) I think the chances have always been high for this system to work well.
-
When your code is running (handling a [[Swing]] event) how can you tell in which thread it is running? Of course, there is {{JDK|java/lang|Thread}}.getName(), but beyond that, there is no other way for your code to find out that now, it runs in {{FX|javafx/application|Platform}}.runLater thread. All event processing remains synchronized (no code runs in parallel), so how could your code tell it is running in different thread? No chance, that is why I believe this change is completely safe.
+
When your code is running (handling a [[Swing]] event) how can you tell in which thread it is running? Of course, there is {{JDK|java/lang|Thread}}.getName(), but beyond that, there is no way for your code to see any differences between the old ''AWT-EventQueue-X'' thread and new {{FX|javafx/application|Platform}}.runLater thread. All event processing remains synchronized (no code runs in parallel), so how could your code tell it is running in different thread? No chance, that is why I believe this change is completely safe.
-
I am not sure in which version of [[JavaFX]] this improved interoperability will be available (it requires changes on the [[JDK]] side as well), but I hope that it lands at least in [[JDK]]8. I am looking forward, as that will greatly improve life for guys trying to mix [[Swing]] with [[JavaFX]].
+
The change has been integrated as http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/ae4683a6b860 and is available in [[JDK]]8. To greatly improve life for guys trying to mix [[Swing]] with [[JavaFX]] just do following before instantiating your AWT and FX objects:
 +
 
 +
<source lang="java">
 +
public static void main(String... args) {
 +
System.setProperty("javafx.embed.singleThread", "true");
 +
SwingUtilities.invokeLater(new Runnable() {
 +
@Override
 +
public void run() {
 +
JFrame frame = new JFrame("FX");
 +
final JFXPanel fxPanel = new JFXPanel();
 +
frame.add(fxPanel);
 +
frame.setVisible(true);
 +
 +
// Swing and JavaFX threads are the same
 +
Scene scene = createScene();
 +
fxPanel.setScene(scene);
 +
}
 +
});
 +
}
 +
</source>
 +
 
 +
The only problem is that this change has been integrated only for [[OS X]] toolkit! I am not sure what the [[Swing]] guys were smoking? Why they didn't integrate the behavior into all AWT toolkits?
 +
 
 +
But who cares about [[JavaFX]] anymore, when the future is in [[DukeScript]], right?
<comments/>
<comments/>

Current revision

JavaFX is new, modern UI toolkit for rendering Java UIs. The idea is tempting - instead of bloated AWT with Swing on top, one can use a completely independent UI and lightweight library (which can for example be deployed to iOS) instead. However, as usual when offering AlternativeBehaviour, the problem is co-existence - there are tons of Swing applications around and they need to migrate to JavaFX in an incremental fashion. Unless such migration is smooth, people will rather stick with what they have right now.

Dispatch Threads

Up until today (e.g. May 2012) mixing Swing and JavaFX was not easy because each of these two systems used its own dispatch thread. Whenever one needed to operate with Swing one had to enter the dispatch thread by using EventQueue.invokeLater(Runnable). As soon as there was a need to manipulate with JavaFX components one had to use Platform.runLater(Runnable). As Java is not very good at this kind of actor based coding, the result was completely unreadable code full of deeply nested Runnables. Here is very simple example:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
             JFrame frame = new JFrame("FX");
             final JFXPanel fxPanel = new JFXPanel();
             frame.add(fxPanel);
             frame.setVisible(true);
 
             Platform.runLater(new Runnable() {
                 @Override
                 public void run() {
                     // This method is invoked on JavaFX thread
                     Scene scene = createScene();
                     fxPanel.setScene(scene);
                 }
             });
        }
    });
}

I am proud to announce that the mutual Swing and JavaFX interoperability has been greatly simplified during May 2012. No need for massive amount of asynchronous Runnables! Your Swing code can directly talk to JavaFX data structures and your JavaFX code can do the same to Swing objects. This is a small change, but huge step forward for Swing+JavaFX interoperability!

The basic idea is to share the Swing and JavaFX dispatch threads. Trivial implementation would keep the AWT-EventQueue-X and just make sure one will always use Platform.runLater to dispatch the Swing events. More advanced implementation can even eliminate the need for AWT-EventQueue-X thread completely (as the patch shows). By running the event processing in the same thread, it is safe to access Swing as well as JavaFX APIs directly which greatly simplifies the coding model.

I've send my patch to Artem (Oracle's JavaFX guru) as a sketch of what could be done and the news from Artem are really great. The basic interoperability seems to work fine. Originally I was slightly afraid whether processing of events in different thread will work seamlessly, but now (when it has been experimentally verified) I think the chances have always been high for this system to work well.

When your code is running (handling a Swing event) how can you tell in which thread it is running? Of course, there is Thread.getName(), but beyond that, there is no way for your code to see any differences between the old AWT-EventQueue-X thread and new Platform.runLater thread. All event processing remains synchronized (no code runs in parallel), so how could your code tell it is running in different thread? No chance, that is why I believe this change is completely safe.

The change has been integrated as http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/ae4683a6b860 and is available in JDK8. To greatly improve life for guys trying to mix Swing with JavaFX just do following before instantiating your AWT and FX objects:

public static void main(String... args) {
  System.setProperty("javafx.embed.singleThread", "true");
  SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
          JFrame frame = new JFrame("FX");
          final JFXPanel fxPanel = new JFXPanel();
          frame.add(fxPanel);
          frame.setVisible(true);
 
          // Swing and JavaFX threads are the same
          Scene scene = createScene();
          fxPanel.setScene(scene);
      }
  });
}

The only problem is that this change has been integrated only for OS X toolkit! I am not sure what the Swing guys were smoking? Why they didn't integrate the behavior into all AWT toolkits?

But who cares about JavaFX anymore, when the future is in DukeScript, right?

<comments/>

Personal tools
buy