Upload
thierry-wasylczenko
View
704
Download
1
Tags:
Embed Size (px)
DESCRIPTION
JavaFX 8 est disponible depuis mars 2014 et apporte son lot de nouveautés. Gradle est en version 2 depuis juillet 2014. Deux technologies plus que prometteuses: JavaFX donne un coup de jeune au développement d’applications desktop en Java en apportant un navigateur web intégré, le support des WebSockets, de la 3D, et bien d’autres. Gradle est l’outil de d’automatisation de build à la mode, apportant de superbes possibilités par rapport rapport à maven, outil vieillissant, grâce à l’engouement de la communauté vis à vis de cet outil mais aussi par le fait de la technologie utilisée en son sein: groovy. Venez découvrir comment il est possible de réaliser rapidement une application à la mode en JavaFX avec un outil à la mode également. Bref venez à une session trendy.
Citation preview
Construire une application JavaFX 8 avecgradle
Thierry Wasylczenko
@twasyl
Construire une application JavaFX 8 avec gradleLa session trendy
3
Ce dont on va parler
• JavaFX 8
• gradle
• Tooling
• De code
4
#JavaFX 8:
5
De 2 à 8
Les Properties
Les types
IntegerProperty intP = new SimpleIntegerProperty();
DoubleProperty doubleP = new SimpleDoubleProperty();
// ...
BooleanProperty booleanP = new SimpleBooleanProperty();
StringProperty stringP = new SimpleStringProperty();
ObjectProperty<SoftShake> objectP = new SimpleObjectProperty();
8
Le binding
IntegerProperty intP1 = new SimpleIntegerProperty();
IntegerProperty intP2 = new SimpleIntegerProperty();
intP1.bind(intP2);
intP2.set(10);
System.out.println("Et P1? " + intP1.get());
9
Le binding
IntegerProperty intP1 = new SimpleIntegerProperty();
IntegerProperty intP2 = new SimpleIntegerProperty();
intP1.bindBidirectional(intP2);
intP2.set(10);
System.out.println("Et P1? " + intP1.get());
intP1.set(20);
System.out.println("Et P2? " + intP2.get());
10
Les événements
IntegerProperty intP1 = new SimpleIntegerProperty();
intP1.addListener((valueInt, oldInt, newInt) -> {
System.out.println("Change");
});
intP1.set(10);
11
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 softShake = new Conference();
tf.textProperty().bindBidirectional(softShake.nameProperty());
12
Pas serializable
POJO 1.5
public class Conference {
private PropertyChangeStatus pcs =
new PropertyChangeStatus(this);
private String name;
public void addPropertyChangeListener(PropertyChangeListener listener)
this.pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener)
this.pcs.removePropertyChangeListener(listener);
14
POJO 1.5
final Conference softShake = new Conference();
JavaBeanStringPropertyBuilder builder = new ...
JavaBeanStringProperty nameProperty = builder.bean(softShake)
.name("name")
.build();
nameProperty.addListener((valueName, oldIName, newName) -> {
// ...
});
15
Vues
FXML
<AnchorPane xmlns:fx="http://javafx.com/fxml"
fx:controller="org.mycompany.Controller">
<stylesheets>
<URL value="@/org/mycompany/css/Default.css" />
<URL value="@/org/mycompany/css/Specialized.css" />
</stylesheets>
<Button fx:id="myButton" text="Button" onAction="#click" />
<TextField fx:id="myTextField" promptText="Enter something" />
</AnchorPane>
17
Controller
public class Controller implements Initializable {
@FXML private Button myButton;
@FXML private TextField myTextField;
@FXML private void click(ActionEvent evt) { /* ... */ }
@Override
public void initialize(URL url, ResourceBundle resourceBundle)
// ...
}
}
18
CSS
Personnaliser les composants
FXML
<Button style="-fx-text-fill: white" styleClass="awesome" />
Java
button.setStyle("-fx-background-color: red;");
button.getStyleClass().add("awesome");
20
Personnaliser les composants
Feuille de style
.button {
-fx-text-fill: white;
-fx-background-color: red;
}
.button:hover { -fx-background-color: blue; }
.awesome { -fx-background-color: gray; }
#myButton { -fx-text-fill: black; }
21
PseudoState personnalisés
PseudoClass ps = PseudoClass.getPseudoClass("awesome");
myButton.pseudoClassStateChanged(ps, true);
.button:awesome {
-fx-text-fill: orange;
}
#myButton:awesome {
-fx-text-fill: green;
}
22
WebView
JS <> JFX
webview.getEngine().getLoadWorker().stateProperty().addListener((observableValue, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) webview.getEngine()
.executeScript("window");
window.setMember("javaObj",this);
}
});
24
JS <> JFX
Java
WebEngine engine = webview.getEngine();
String result = engine.executeScript("return 'Hello';");
JavaScript
javaObj.myWonderfulMethod("Hello");
25
WebSocket
window.onload = function() {
socket = new WebSocket("ws://mycompany.com/ws");
socket.onopen = function(event) { /* ... */ };
socket.onclose = function(event) { /* ... */ };
socket.onmessage = function(event) { /* ... */ };
};
26
Drag'n'drop
Drag'n'drop
obj.setOnDragDetected(event -> { /* ... */ });
obj.setOnDragOver(event -> { /* ... */ });
obj.setOnDragEntered(event -> { /* ... */ });
obj.setOnDragExited(event -> { /* ... */ });
obj.setOnDragDropped(event -> { /* ... */ });
obj.setOnDragDone(event -> { /* ... */ });
28
Printing API
Chaque Node
PrinterJob job = PrinterJob.createPrinterJob();
job.printPage(myTextField);
Une page web
WebView view = new WebView();
PrinterJob job = PrinterJob.createPrinterJob();
view.getEngine().print(job);
30
3D
Objets prédéfinis
Box b = new Box(width, height, depth);
Cylinder c = new Cylinder(radius, height);
Sphere s = new Sphere(radius);
TriangleMesh tm = new TriangleMesh();
Les plus basiques
32
Camera & Light
Camera camera = new PerspectiveCamera(true);
scene.setCamera(camera);
PointLight point = new PointLight(Color.RED);
AmbientLight ambient = new AmbientLight(Color.WHITE);
scene.getRoot().getChildren().addAll(point, ambient);
Ne pas oublier de positionner les objets
33
#gradle:
34
Flexibilité
Task
• Réponds à MON besoin
• Dynamisme
• Dépendances
• Greffage au cycle de vie
task sofshake << {
println 'Hello Soft-Shake 2014'
}
tasks['sofshake'].dependsOn 'jar'
36
Task: surcharge
apply plugin: 'java'
task jar(overwrite: true) << {
// ...
manifest {
// ...
}
}
37
Dépendances
dependencies {
compile (':my-project')
runtime files('libs/a.jar', 'libs/b.jar')
runtime "org.groovy:groovy:2.2.0@jar"
runtime group: 'org.groovy', name: 'groovy', version: '2.2.0', ext:
}
38
Copy
• Copier des fichiers facilement
• La roue est déjà inventée
copy {
from file1
from file2
into folder
}
39
Gradle wrapper
• Execution de gradle sans intallation préalable
• Plateformes d’intégration continue friendly
task buildGradleWrapper(type: Wrapper) {
gradleVersion = '2.1'
}
40
Ouvert
Intégration de Ant
• Variables
• Tâches
ant.importBuild "ant/project/file.xml"
ant.conference = "Soft-Shake 2014"
ant.location = "Genève"
maTacheAnt.execute()
44
Tooling
45
SceneBuilder 46
ScenicView 47
TestFX
public class DesktopTest extends GuiTest {
public Parent getRootNode() { return new Desktop(); }
@Test public void testMe() {
// Given
rightClick("#desktop").move("New").click("Text Document")
.type("myTextfile.txt").push(ENTER);
// When
drag(".file").to("#trash-can");
// Then
verifyThat("#desktop", contains(0, ".file"));
48
#Code
49
Codons !
• JavaFX 8
• Properties
• FXML
• Styling
• gradle
• Dépendances
• Build
50
Ressources 51
Ressources
• https://github.com/TestFX/TestFX
• http://fxexperience.com/
• http://fxexperience.com/controlsfx/
• Source code of the demo: https://bitbucket.org/twasyl/weatherfx
52
53