Эффект JavaFX на фоне
Я использую этой чтобы сделать iOS-тематическое приложение JavaFX2 (Java7) с эффектом матового стекла. Проблема в том, что этот код использует свое влияние на книги. Я бы хотел, чтобы он использовал свое влияние на то, что находится за окном, например:
есть ли вообще это сделать? Мне также нравится этот небольшой эффект тени, который вы видите вокруг вышеуказанного изображения.
чтобы быть ясным, я не хочу, чтобы этот слайдер или что-то еще, просто эффект бытия способный видеть через окно и имеющий эту небольшую тень по краям. Я хочу использовать этот эффект iOS7-ish вместо aero, хотя.
Это может быть важно: я использую модифицированную версию Undecorator.
4 ответов
import javafx.animation.*;
import javafx.application.*;
import javafx.beans.property.*;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.effect.*;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.image.*;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
public class FrostyTech extends Application {
private static final double BLUR_AMOUNT = 10;
private static final Effect frostEffect =
new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);
private static final ImageView background = new ImageView();
private static final StackPane layout = new StackPane();
@Override public void start(Stage stage) {
layout.getChildren().setAll(background, createContent());
layout.setStyle("-fx-background-color: null");
Scene scene = new Scene(
layout,
200, 300,
Color.TRANSPARENT
);
Platform.setImplicitExit(false);
scene.setOnMouseClicked(event -> {
if (event.getClickCount() == 2) Platform.exit();
});
makeSmoke(stage);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setScene(scene);
stage.show();
background.setImage(copyBackground(stage));
background.setEffect(frostEffect);
makeDraggable(stage, layout);
}
// copy a background node to be frozen over.
private Image copyBackground(Stage stage) {
final int X = (int) stage.getX();
final int Y = (int) stage.getY();
final int W = (int) stage.getWidth();
final int H = (int) stage.getHeight();
try {
java.awt.Robot robot = new java.awt.Robot();
java.awt.image.BufferedImage image = robot.createScreenCapture(new java.awt.Rectangle(X, Y, W, H));
return SwingFXUtils.toFXImage(image, null);
} catch (java.awt.AWTException e) {
System.out.println("The robot of doom strikes!");
e.printStackTrace();
return null;
}
}
// create some content to be displayed on top of the frozen glass panel.
private Label createContent() {
Label label = new Label("Create a new question for drop shadow effects.\n\nDrag to move\n\nDouble click to close");
label.setPadding(new Insets(10));
label.setStyle("-fx-font-size: 15px; -fx-text-fill: green;");
label.setMaxWidth(250);
label.setWrapText(true);
return label;
}
// makes a stage draggable using a given node.
public void makeDraggable(final Stage stage, final Node byNode) {
final Delta dragDelta = new Delta();
byNode.setOnMousePressed(mouseEvent -> {
// record a delta distance for the drag and drop operation.
dragDelta.x = stage.getX() - mouseEvent.getScreenX();
dragDelta.y = stage.getY() - mouseEvent.getScreenY();
byNode.setCursor(Cursor.MOVE);
});
final BooleanProperty inDrag = new SimpleBooleanProperty(false);
byNode.setOnMouseReleased(mouseEvent -> {
byNode.setCursor(Cursor.HAND);
if (inDrag.get()) {
stage.hide();
Timeline pause = new Timeline(new KeyFrame(Duration.millis(50), event -> {
background.setImage(copyBackground(stage));
layout.getChildren().set(
0,
background
);
stage.show();
}));
pause.play();
}
inDrag.set(false);
});
byNode.setOnMouseDragged(mouseEvent -> {
stage.setX(mouseEvent.getScreenX() + dragDelta.x);
stage.setY(mouseEvent.getScreenY() + dragDelta.y);
layout.getChildren().set(
0,
makeSmoke(stage)
);
inDrag.set(true);
});
byNode.setOnMouseEntered(mouseEvent -> {
if (!mouseEvent.isPrimaryButtonDown()) {
byNode.setCursor(Cursor.HAND);
}
});
byNode.setOnMouseExited(mouseEvent -> {
if (!mouseEvent.isPrimaryButtonDown()) {
byNode.setCursor(Cursor.DEFAULT);
}
});
}
private javafx.scene.shape.Rectangle makeSmoke(Stage stage) {
return new javafx.scene.shape.Rectangle(
stage.getWidth(),
stage.getHeight(),
Color.WHITESMOKE.deriveColor(
0, 1, 1, 0.08
)
);
}
/** records relative x and y co-ordinates. */
private static class Delta {
double x, y;
}
public static void main(String[] args) {
launch(args);
}
}
Вопросы
визуальный эффект, который вы хотите для зависящего от ОС оформления окна, может быть достигнут только через API, которые предоставляет ОС. И таким образом был устранен StageStyle.TRANSPARENT
ниже.
для самого контента JavaFX вы можете управлять визуальными эффектами stage > scene > root pane
иерархии. Сцена и сцена не поддерживают (и не направлены) передовые стилизации, поэтому были устранены путем установки как прозрачные ниже.
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
root.setStyle("-fx-background-color: null;");
root.setPadding(new Insets(10));
DoubleProperty doubleProperty = new SimpleDoubleProperty(0);
Region region = new Region();
region.styleProperty().bind(Bindings
.concat("-fx-background-radius:20; -fx-background-color: rgba(56, 176, 209, ")
.concat(doubleProperty)
.concat(");"));
region.setEffect(new DropShadow(10, Color.GREY));
Slider slider = new Slider(0, 1, .3);
doubleProperty.bind(slider.valueProperty());
root.getChildren().addAll(region, slider);
primaryStage.initStyle(StageStyle.TRANSPARENT);
Scene scene = new Scene(root, 300, 250);
scene.setFill(Color.TRANSPARENT);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
однако влияние тени падения не играет хорошо с значением Альфы цвет фона. Вы можете наблюдать это, изменив цвет тени на другой контрастный.
выход:
чтобы расширить ответ Jewlsea .. И используя приведенный выше пример только с JavaFX ..
хотя классы не являются общедоступными API, он полностью избегает стека AWT. Вот это non public пример :
// copy a background node to be frozen over.
private Image copyBackground(Stage stage) {
final int X = (int) stage.getX();
final int Y = (int) stage.getY();
final int W = (int) stage.getWidth();
final int H = (int) stage.getHeight();
final Screen screen = Screen.getPrimary();
try {
Robot rbt = com.sun.glass.ui.Application.GetApplication().createRobot();
Pixels p = rbt.getScreenCapture(
(int)screen.getBounds().getMinX(),
(int)screen.getBounds().getMinY(),
(int)screen.getBounds().getWidth(),
(int)screen.getBounds().getHeight(),
true
);
WritableImage dskTop = new WritableImage((int)screen.getBounds().getWidth(), (int)screen.getBounds().getHeight());
dskTop.getPixelWriter().setPixels(
(int)screen.getBounds().getMinX(),
(int)screen.getBounds().getMinY(),
(int)screen.getBounds().getWidth(),
(int)screen.getBounds().getHeight(),
PixelFormat.getByteBgraPreInstance(),
p.asByteBuffer(),
(int)(screen.getBounds().getWidth() * 4)
);
WritableImage image = new WritableImage(W,H);
image.getPixelWriter().setPixels(0, 0, W, H, dskTop.getPixelReader(), X, Y);
return image;
} catch (Exception e) {
System.out.println("The robot of doom strikes!");
e.printStackTrace();
return null;
}
}
результаты с небольшой dropshadow добавил:
DropShadow shdw = new DropShadow();
shdw.setBlurType(BlurType.GAUSSIAN);
shdw.setColor(Color.GAINSBORO);
shdw.setRadius(10);
shdw.setSpread(0.12);
shdw.setHeight(10);
shdw.setWidth(10);
layout.setEffect(shdw);
непрозрачность является свойством Node, который является родительским классом в JavaFX для вещей, которые появляются на экране. http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#opacityProperty
таким образом, вы можете просто установить непрозрачность объекта, который вы хотите, чтобы исчезнуть. Затем вам нужно добавить какой-то способ изменить непрозрачность на желаемом объекте. Использование слайдера из вашего изображения-один из способов, но есть и другие.
тени могут быть сделано с помощью эффекта DropShadow... http://docs.oracle.com/javafx/2/api/javafx/scene/effect/DropShadow.html. Я никогда им не пользовался. Это немного высокий уровень, но если есть вопросы в комментариях, я могу помочь ответить на них.