Using BoxShadow is a very common thing in modern UIs, so it might not be suprising that designers defining UIs often also use them heavily.
Unfortunately JavaFX has NO 100% compatible effect and even worse one who is closest (DropShadow) leads to a massive performance hit as shown in this video
On the left hand side is a Node who has a DropShadow-Effect applied to it and you notice that once the effect is applied that the animation isn’t smooth any more. On the right hand side you see a new Node we’ll release with e(fx)clipse 3.7.0 who provides a new BoxShadow-Node (named BoxShadow2).
Beside getting a huge performance win, the BoxShadow-Node uses the same semantics the browser counterpart does so you can port CSS definition to your JavaFX-Application.
For completness here’s the code for this demo video.
package org.eclipse.fx.ui.controls.demo; import org.eclipse.fx.ui.controls.effects.BoxShadow2; import javafx.animation.Animation; import javafx.animation.Animation.Status; import javafx.animation.TranslateTransition; import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.effect.DropShadow; import javafx.scene.layout.BorderPane; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.stage.Stage; import javafx.util.Duration; public class InTheShadow extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws Exception { BorderPane p = new BorderPane(); p.setPadding(new Insets(20)); Button shadowMe = new Button("Toggle Shadow"); p.setTop(shadowMe); Region pane; if (Boolean.getBoolean("efxclipse-shadow")) { BoxShadow2 shadow = new BoxShadow2(createComplexUI()); shadow.setShadowVisible(false); pane = shadow; } else { pane = new StackPane(createComplexUI()); } p.setCenter(pane); shadowMe.setOnAction(evt -> toggleShadow(pane)); Scene s = new Scene(p, 1200, 800); primaryStage.setTitle("efxclipse-shadow: " + Boolean.getBoolean("efxclipse-shadow")); primaryStage.setScene(s); primaryStage.show(); } private void toggleShadow(Region pane) { if (pane instanceof BoxShadow2) { BoxShadow2 s = (BoxShadow2) pane; s.setShadowVisible(!s.isShadowVisible()); } else { if (pane.getEffect() != null) { pane.setEffect(null); } else { DropShadow dropShadow = new DropShadow(); dropShadow.setRadius(5.0); dropShadow.setOffsetX(3.0); dropShadow.setOffsetY(3.0); dropShadow.setColor(Color.color(0.4, 0.5, 0.5)); pane.setEffect(dropShadow); } } } private Node createComplexUI() { StackPane pane = new StackPane(); pane.setStyle("-fx-background-color: white"); for (int i = 0; i < 100; i++) { Button b = new Button("Button " + i); b.setTranslateX(i % 100); pane.getChildren().add(b); } Button animated = new Button("Animated"); StackPane.setAlignment(animated, Pos.BOTTOM_CENTER); TranslateTransition t = new TranslateTransition(Duration.millis(1000), animated); t.setAutoReverse(true); t.setFromX(-300); t.setToX(300); t.setCycleCount(Animation.INDEFINITE); animated.setOnAction(evt -> { if (t.getStatus() == Status.RUNNING) { t.pause(); } else { t.play(); } }); pane.getChildren().add(animated); return pane; } }
Pingback: e(fx)clipse 3.7.0 is released | Tomsondev Blog