Efecto de vidrio esmerilado en JavaFX?

Estoy haciendo un proyecto JavaFX2 / FXML con tema iOS7 y me preguntaba cómo podría hacer que un objeto Rectangle tenga un efecto de vidrio esmerilado tipo iOS7.

También me gustaría que tenga una pequeña sombra. Esto es complicado, ya que es posible que pueda ver la sombra detrás del objeto semitransparente. Me gustaría que esté presente en los bordes.

es posible? Aquí hay una imagen que muestra el efecto deseado (sin incluir la pequeña sombra paralela):

Me gustaría que se vea así

ACTUALIZACIÓN: Aquí hay una continuación del problema. Esto se verá increíble: D.

Solución de muestra

escarcha

Ejecute el progtwig a continuación y desplácese o deslice hacia arriba para mostrar el panel de cristal.

El propósito del progtwig es simplemente muestrear las técnicas involucradas para no actuar como una biblioteca de propósito general para el efecto de escarcha.

import javafx.animation.*; import javafx.application.Application; import javafx.beans.property.*; import javafx.geometry.Rectangle2D; import javafx.scene.*; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.effect.*; import javafx.scene.image.*; import javafx.scene.input.ScrollEvent; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import javafx.util.Duration; // slides a frost pane in on scroll or swipe up; slides it out on scroll or swipe down. public class Frosty extends Application { private static final double W = 330; private static final double H = 590; private static final double BLUR_AMOUNT = 60; private static final Duration SLIDE_DURATION = Duration.seconds(0.4); private static final double UPPER_SLIDE_POSITION = 100; private static final Effect frostEffect = new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3); @Override public void start(Stage stage) { DoubleProperty y = new SimpleDoubleProperty(H); Node background = createBackground(); Node frost = freeze(background, y); Node content = createContent(); content.setVisible(false); Scene scene = new Scene( new StackPane( background, frost, content ) ); stage.setScene(scene); stage.show(); addSlideHandlers(y, content, scene); } // create a background node to be frozen over. private Node createBackground() { Image backgroundImage = new Image( getClass().getResourceAsStream("ios-screenshot.png") ); ImageView background = new ImageView(backgroundImage); Rectangle2D viewport = new Rectangle2D(0, 0, W, H); background.setViewport(viewport); return background; } // create some content to be displayed on top of the frozen glass panel. private Label createContent() { Label label = new Label("The overlaid text is clear and the background below is frosty."); label.setStyle("-fx-font-size: 25px; -fx-text-fill: midnightblue;"); label.setEffect(new Glow()); label.setMaxWidth(W - 20); label.setWrapText(true); return label; } // add handlers to slide the glass panel in and out. private void addSlideHandlers(DoubleProperty y, Node content, Scene scene) { Timeline slideIn = new Timeline( new KeyFrame( SLIDE_DURATION, new KeyValue( y, UPPER_SLIDE_POSITION ) ) ); slideIn.setOnFinished(e -> content.setVisible(true)); Timeline slideOut = new Timeline( new KeyFrame( SLIDE_DURATION, new KeyValue( y, H ) ) ); scene.setOnSwipeUp(e -> { slideOut.stop(); slideIn.play(); }); scene.setOnSwipeDown(e -> { slideIn.stop(); slideOut.play(); content.setVisible(false); }); // scroll handler isn't necessary if you have a touch screen. scene.setOnScroll((ScrollEvent e) -> { if (e.getDeltaY() < 0) { slideOut.stop(); slideIn.play(); } else { slideIn.stop(); slideOut.play(); content.setVisible(false); } }); } // create a frosty pane from a background node. private StackPane freeze(Node background, DoubleProperty y) { Image frostImage = background.snapshot( new SnapshotParameters(), null ); ImageView frost = new ImageView(frostImage); Rectangle filler = new Rectangle(0, 0, W, H); filler.setFill(Color.AZURE); Pane frostPane = new Pane(frost); frostPane.setEffect(frostEffect); StackPane frostView = new StackPane( filler, frostPane ); Rectangle clipShape = new Rectangle(0, y.get(), W, H); frostView.setClip(clipShape); clipShape.yProperty().bind(y); return frostView; } public static void main(String[] args) { launch(args); } } 

Imagen de origen

Guarde esta imagen paralela a la fuente de Java como un archivo llamado ios-screenshot.png y ios-screenshot.png que su sistema de comstackción lo copie en el directorio de destino para la salida binaria de la comstackción.

ios-captura de pantalla

Respuestas a preguntas adicionales

"JDK 8", ¿sería eso un requisito?

El código de ejemplo anterior está escrito contra JDK 8. Devolverlo a JDK 7 reemplazando las llamadas lambda con clases internas anónimas es bastante trivial.

En general, Java 7 está bastante anticuado para el trabajo de JavaFX. Aconsejo actualizar lo antes posible para trabajar con una versión mínima de Java 8.

iniciando sus paneles con argumentos

Constructores más convenientes para la mayoría de los nodos principales es una característica de Java 8 . Puede convertir fácilmente el formato Java 8:

  StackPane stack = new StackPane(child1, child2); 

Para Java 7:

  StackPane stack = new StackPane(); stack.getChildren().setAll(child1, child2); 

¿Funcionará esto si el escritorio está detrás de un panel helado?

No directamente, puedes crear una nueva pregunta para eso.

Actualización: preguntas relacionadas

Usuario creado: efecto JavaFX en el fondo para permitir que el efecto helado se aplique a una ventana sobre un fondo de escritorio.

Otro usuario creado: ¿Cómo creo un escenario transparente JavaFX con sombras solo en el borde? para aplicar un efecto de sombreado de halo alrededor de esta ventana.