Gdy pracujemy z klasą Subscene
i elementami 3D, możemy potrzebować specjalnego tła dla aplikacji, do którego użytkownik nie powinien mieć dostępu.
Klasa Listing11c_18c.java
package rozdzial11c; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Bounds; import javafx.scene.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Box; import javafx.scene.shape.Cylinder; import javafx.scene.shape.Sphere; import javafx.scene.transform.Translate; import javafx.stage.Stage; import javafx.util.Duration; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; public class Listing11_18c extends Application { private Timeline timeline; private BufferedInputStream bis; public static void main(String[] args) { Application.launch(args); } @Override public void init() { try { FileInputStream is = new FileInputStream( "rozdzial11c/src/rozdzial11c/kwiatek.jpg"); bis = new BufferedInputStream(is); } catch (FileNotFoundException e) { e.printStackTrace(); } } @Override public void start(Stage stage) { //--------------- subScene ----------------------- Image image = new Image(bis); ImageView iv = new ImageView(); iv.setImage(image); iv.setFitWidth(256); iv.setFitHeight(192); iv.setSmooth(true); iv.setCache(true); iv.relocate(100, 75); Pane sroot = new Pane(); sroot.getChildren().addAll(iv); SubScene s = new SubScene(sroot,500, 400); //---------------------- 3d ----------------------- Group group = new Group(); Sphere sphere = new Sphere(50); Translate trans1 = new Translate(-100, 0, 100); sphere.getTransforms().add(trans1); Cylinder cyli = new Cylinder(30, 100); Translate trans2 = new Translate(20, 0, 100); cyli.getTransforms().add(trans2); Box box = new Box(100, 100, 100); Translate trans3 = new Translate(140, 0, 100); box.getTransforms().add(trans3); PointLight al = new PointLight(); al.setColor(Color.RED); group.getChildren().addAll(sphere, box, cyli, al); //---------------------- all ---------------------- StackPane mroot = new StackPane(); mroot.getChildren().addAll(s, group); Scene scene = new Scene(mroot, 500, 400, false, SceneAntialiasing.BALANCED); stage.setTitle("Bouncing Image"); stage.setScene(scene); stage.show(); EventHandler<ActionEvent> ev = new EventHandler<>() { double dx = 5; double dy = 3; @Override public void handle(ActionEvent t) { iv.setLayoutX(iv.getLayoutX() + dx); iv.setLayoutY(iv.getLayoutY() + dy); Bounds bounds = sroot.getBoundsInLocal(); if (iv.getLayoutX() <= (bounds.getMinX()) || iv.getLayoutX() >= (bounds.getMaxX() - iv.getFitWidth())) { dx = -dx; } if (iv.getLayoutY() >= (bounds.getMaxY() - iv.getFitHeight()) || iv.getLayoutY() <= (bounds.getMinY() )) { dy = -dy; } } }; timeline = new Timeline(new KeyFrame( Duration.millis(40),ev)); timeline.setCycleCount(Timeline.INDEFINITE); timeline.play(); } @Override public void stop() { timeline.stop(); } }
Klasa module-info.java
module rozdzial11c { requires java.desktop; requires javafx.graphics; requires javafx.controls; requires javafx.swing; exports rozdzial11c to javafx.graphics; }
Po uruchomieniu kodu zobaczymy nieruchome bryły 3D, a za nimi samodzielną animację – poruszający się obrazek. Użytkownik nie ma możliwości sterowania tłem.