Date post: | 29-Jun-2015 |
Category: |
Engineering |
Upload: | thierry-wasylczenko |
View: | 702 times |
Download: | 1 times |
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