REX about JavaFX8 used in SlideshowFX. This presentation covers concept from JavaFX as well as technologies like OSGi, Vert.x, LeapMotion, nashorn and friends in order to make them communicate inside one application developed in JavaFX.
This presentation was made at the FinistJUG, NantesJUG and NormandyJUG.
2. Disclaimer
Swing lovers won’t be hurt and no beard or mustach will be shaved.
You will maybe discover new technologies or concepts. Don’t be
afraid.
The presentation of technologies are not promotional.
SlideshowFX is my own open source project and will only be used as
an example of implementations of technologies presented.
2
3. presentation.agenda()
public class Presentation extends Application {
public void init() { Speaker.load("twasyl"); }
public void start(Stage stage) {
JavaFX.getVersion(8).load();
new ScriptEngineManager().getEngineByName("nashorn");
Bundle.deploy("OSGi");
Markups.stream().filter(m -> m.name.equals("asciidoctor")));
vertx.createHttpServer().listen(8080, "localhost");
leapMotionController.isConnected();
}
public void stop() { Speaker.shutdown("twasyl"); }
}
3
6. Pourquoi le OuestFX tour?
Un espagnol breton perdu en Normandie nous refait l'histoire des
ihm en java c'est @LostInBrittany au @normandyjug
8:03 PM - 14 Oct 2014
Yann PETIT
@finalspy
Follow
2 RETWEETS 1 FAVORITE
6
7. Pourquoi le OuestFX tour?
@finalspy @LostInBrittany @normandyjug Il a parlé #JavaFX au moins?
Thierry Wasylczenko @twasyl
@twasyl @finalspy @normandyjug #javafx ? Moi j'ai fait
du vrai client lourd, j'ai fait du #swing :p
9:33 AM - 15 Oct 2014 Paris, Ile-de-France, France
Horacio Gonzalez
@LostInBrittany
Follow
1 RETWEET
15 Oct
7
13. FXML-the controller
• The backend of FXML
• Associated to the view
public class MyController implements Initializable {
// Some interesting things to code
@Override
public void initialize(URL url, ResourceBundle resourceBundle)
// Some other interesting things to code !
}
}
13
28. Properties -POJO 2.0
public class Conference {
private StringProperty name = new SimpleStringProperty();
public StringProperty nameProperty() { return this.name; }
public String getName() { return this.name.get(); }
public void setName(String name) { this.name.set(name); }
}
final Conference jug = new Conference();
tf.textProperty().bindBidirectional(jug.nameProperty());
28
30. Properties -POJO 1.5
public class Conference {
private PropertyChangeStatus pcs =
new PropertyChangeStatus(this);
private String name;
public void addPropertyChangeListener(PropertyChangeListener list
this.pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener l
this.pcs.removePropertyChangeListener(listener);
}
30
31. Properties -POJO 1.5
public class Conference {
// ...
public void addPropertyChangeListener(String propertyName, Proper
this.pcs.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(String propertyName, Pro
this.pcs.removePropertyChangeListener(propertyName, listener);
}
// ...
}
31
32. Properties -POJO 1.5
public class Conference {
// ...
public String getName() { return this.name; }
public void setName(String name) {
final String old = this.name;
this.name = name;
this.pcs.firePropertyChange("name", old, this.name);
}
}
32
33. Properties -POJO 1.5
final Conference jug = new Conference();
JavaBeanStringPropertyBuilder builder = new ...
JavaBeanStringProperty nameProperty = builder.bean(jug)
.name("name")
.build();
nameProperty.addListener((valueName, oldIName, newName) -> {
// ...
});
33
37. ImageView-Java
final URL url = ...
final InputStream stream = ...
final Image image1 = new Image(url, true);
final Image image2 = new Image(stream);
final ImageView view = new ImageView(image1);
• Prefer the Image contructor with a URL
37
39. WebView-the State
final WebView browser = new WebView();
browser.getEngine().stateProperty().addListener((stateValue, oldSta
if(newState == Worker.State.SUCCEEDED) {
final Element div = browser.getEngine().getDocument()
.getElementById("twasyl");
if(div != null) {
div.getTextContent();
}
}
});
39
50. • Questions:
1. How to not block my UI when I
download a file ?
2. How to work with the file when
download is done ?
• javafx.concurrent
• Worker
• Task
• Service
• ScheduledService
concurrency.setTricky(true) 50
63. • Execute Java from JavaScript
$ jjs java.js
[Hello, world]
Nashorn
function displayList() {
var ArrayList = Java.type('java.util.ArrayList'
var lst = new ArrayList();
lst.add("Hello");
lst.add("world");
print(lst);
}
63
64. Nashorn -embedding
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("nashorn");
engine.eval("function sum(a, b) { return a + b; }");
System.out.println(engine.eval("sum(1, 2);"));
64
65. • Useful ?
• Web-based app
• One browser to test
• Web developer for front
• Java deveveloper for back
• SlideshowFX
• Polyglotism
Nashorn -JavaFX 65
66. Nashorn -JavaFX
WebView webView = new WebView();
// Make a Java object available in the page
JSObject window = (JSObject) webView.getEngine()
.executeScript("window");
window.setMember("sfx", SlideshowFXController.this);
// Execute some JavaScript
webView.getEngine().executeScript("sum(1, 2);");
66
67. • What’s done:
• DOM manipulation
• Get current slide
• Inject custom JS libraries
• Advantages
• JavaFX – HTML communication
• Tip
• Use Base64 strings for interopability
Nashorn -SlideshowFX
REX
67
77. • Simplified syntax for complex rendering
• Diagrams
• Formulas
• Written in Ruby
• Ports
• JavaScript
• JVM
The popular syntax 77
78. AsciidoctorJ & OSGi
• Parse asciidoctor in Java
• from files
• from strings
RubyInstanceConfig config = new RubyInstanceConfig();
config.setLoader(AsciidoctorMarkup.class.getClassLoader());
JavaEmbedUtils.initialize(Arrays.asList("gems/asciidoctor-1.5.2/lib
Asciidoctor asciidoctor = Asciidoctor.Factory
.create(AsciidoctorMarkup.class.getClassLoader());
78
79. Asciidoctor -Parsing
• From strings
String html = asciidoctor.convert("I'm a hero",
new HashMap<String, Object>());
• From files
File myFile = new File("myFile.adoc");
List<File> myFiles = new ArrayList<>(); // Add files then
Map<String, Object> options = new HashMap<>();
String html = asciidoctor.convertFile(myFile, options);
String[] htmls = asciidoctor.convertFiles(myFiles, options);
79
80. • Markup syntax
• OSGi context
• Advantage
• Trendy way to define slides' content
• Tip
• Usage in an OSGi context requires a
lot of attention
Asciidoctor -SlideshowFX
REX
80
82. • Lightweight for the JVM
• Polyglot components
• Java
• JavaScript
• Groovy
• CoffeeScript
• Python
• Ruby
• ...
Innovative JVM server 82
83. Vert.x-Verticles
• Verticle = piece of the server
• Do some things
• Each Verticle has an instance of Vertx
public class MyVerticle extends Verticle {
@Override
public void start() {
// Do something
}
}
83
86. Vert.x-Event Bus
• Communicating system between Verticles
• Cross Vert.x instances
Handler<Message<String>> handler = message -> {
System.out.println("Hello" + message.body());
message.reply();
};
this.vertx.eventBus().registerHandler("say.hello", handler);
this.vertx.eventBus().publish("say.hello", "Thierry");
86
87. Vert.x-Shared Data
• Share data between Verticles
• Not cross Vert.x instances
Map serverInfo = vertx.sharedData().getMap("serverInfo");
Set users = vertx.sharedData().getSet("users");
serverInfo.put("ip", "192.168.218.100");
users.add("thierry");
87
88. • What’s done
• Chat using websockets
• Quizz feature
• Twitter integration
• Advantages
• Embed a web server easily
• No installation for the client
• Tip
• Store HttpServer instances as
singleton for re-usage
Vert.x-SlideshowFX
REX
88
92. LeapMotion -The controller
• Main interface with the device
• Access
• Frames
• Configuration information
• Use listeners
Controller leapController = new Controller();
92