Эффект матового стекла в JavaFX?
Я делаю проект JavaFX2/FXML на тему iOS7, и мне было интересно, как я могу сделать объект прямоугольника с эффектом матового стекла iOS7.
Я также хотел бы, чтобы у него была небольшая тень. Это сложно, так как вы можете увидеть тень за полупрозрачным объектом. Я просто хочу, чтобы он присутствовал по краям.
это возможно? Вот изображение, показывающее желаемый эффект (не включая маленький drop-shadow):
обновление: здесь продолжение вопроса. Это будет выглядеть потрясающе: D.
1 ответов
Образец Решения
запустите программу ниже и прокрутите или проведите пальцем вверх, чтобы показать стеклянную панель.
цель программы состоит в том, чтобы просто попробовать методы, связанные не выступать в качестве библиотеки общего назначения для эффекта мороза.
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); }
}
Источник изображения
сохраните это изображение параллельно источнику Java в виде файла с именем ios-screenshot.png
и попросите вашу систему сборки скопировать его в целевой каталог для двоичного вывода сборки.
ответы на дополнительные вопросы
"JDK 8", это было бы требованием этого?
пример кода выше написан против JDK 8. Перенос его обратно в JDK 7 путем замены лямбда-вызовов анонимными внутренними классами довольно тривиален.
В общем, Java 7 довольно устарел для JavaFX работа. Я советую обновить как можно скорее, чтобы работать с минимальной версией Java 8.
инициирование ваших панелей с аргументами
более удобными конструкторами для большинства родительских узлов является функция Java 8. Вы можете легко преобразовать формат Java 8:
StackPane stack = new StackPane(child1, child2);
На Java 7:
StackPane stack = new StackPane();
stack.getChildren().setAll(child1, child2);
будет ли это работать, если рабочий стол находится за морозной панелью?
не напрямую, для этого можно создать новый вопрос.
Обновление: Вопросы
пользователей созданы: эффект JavaFX на фоне чтобы матовый эффект применялся к окну на фоне рабочего стола.
другой пользователь создал: как создать прозрачную сцену JavaFX с тенями только на границе? чтобы применить эффект тени ореола вокруг этого окна.