Frosted Glass Clipping in JavaFX - javafx

I'm trying to achieve this effect here but on a static background (without the scrolling). I'm getting this weird clip on my results though (without the frost effect). I think I know where the problem is in my code but I'm not sure how to solve it.
public class App extends Application {
private static final double BLUR_AMOUNT = 80;
private static final Effect frostEffect = new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
ImageView background = new ImageView(bgImage);
StackPane centerBlurredPane = (StackPane) frozenCenterUI();
BorderPane centerContent = new BorderPane();
centerContent.setCenter(new Text("Center"));
centerContent.setTop(new Text("Top"));
centerContent.setLeft(new Text("Left"));
centerContent.setRight(new Text("Right"));
centerBlurredPane.getChildren.add(centerContent);
Scene scene = new Scene(new StackPane(background,centerBlurredPane),414, 849);
primaryStage.setScene(scene);
primaryStage.show();
}
private Node frozenCenterUI() {
Image frostImage = background.snapshot(new SnapshotParameters(), null);
ImageView frost = new ImageView(frostImage);
Rectangle filler = new Rectangle(24, 762, 366, 696);
filler.setArcHeight(50);
filler.setArcWidth(50);
filler.setFill(Color.AZURE);
Pane frostPane = new Pane(frost);
frostPane.setEffect(frostEffect);
StackPane frostView = new StackPane(filler, frostPane);
Rectangle clipShape = new Rectangle(24, 762, 366, 696);
frostView.setClip(clipShape);
return frostView;
}
}
This is what i'm getting, however. I want to apply frost on the white area here.
What should my clip shape be?
Here's my background image, backgroundImage
Edit: I found that if I change my clipShape to have the same dimensions as the scene, then I get the desired effect. However, the BorderPane I added to the frozen pane is not constrained to it, but actually stretches and fills the entire window.

Related

JavaFX - Child Nodes Overlapping Parent Node (Parent's width smaller than children)

Below there is a quick sample of a JavaFX application where the brown region (parent node) contains two child nodes, a red square and a blue circle. When I am reducing the width of the parent node to a size smaller than those of its children, I was expecting the child nodes to be partially visible. However, this is not the case but instead the child nodes are shown fully over parent's region. Any ideas on how to achieve that on the below example?
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Parent Child Relationship!");
ParentNode parentNode = new ParentNode();
StackPane root = new StackPane();
root.getChildren().add(parentNode);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
class ParentNode extends Region {
private Rectangle square = new Rectangle();
private Circle circle = new Circle();;
public ParentNode() {
square.setWidth(40);
square.setHeight(40);
square.setFill(Color.RED);
circle.radiusProperty().bind(square.heightProperty().divide(3));
circle.centerXProperty().bind(circle.radiusProperty());
circle.centerYProperty().bind(square.heightProperty().divide(2));
circle.setFill(Color.BLUE);
circle.setStroke(Color.LIGHTGRAY);
getChildren().addAll(square, circle);
setBackground(new Background(new BackgroundFill(Color.CHOCOLATE, null, null)));
this.setMaxHeight(100);
this.setMaxWidth(200);
this.setMinHeight(0);
this.setMinWidth(0);
this.setOnMousePressed((e) -> this.setMaxWidth(20));
}
}
The only way i can think of, would be using a rectangle as the clip for the parentNode and binding its height and width to the parentNode's width and height properties, here is a working example:
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Parent Child Relationship!");
ParentNode parentNode = new ParentNode();
parentNode.maxWidthProperty().bind(primaryStage.widthProperty().subtract(200));
Rectangle clip = new Rectangle();
clip.widthProperty().bind(parentNode.widthProperty());
clip.heightProperty().bind(parentNode.heightProperty());
parentNode.setClip(clip);
StackPane root = new StackPane();
root.getChildren().add(parentNode);
primaryStage.setScene(new Scene(root, 400, 250));
primaryStage.show();
}
(i bound the parentNode's width to the windows width just so you see it working while you resize the window)

How to make pane and elements in it resizable when stage size is changing

Can you please tell me how can I realize that the whole content of a pane will be resized while the stage is resized with mousedragg. Here is my code:
public class fab extends Application {
private Stage stage;
private Pane pane;
private Scene scene;
#Override
public void start(Stage stage) throws Exception {
this.stage = stage;
Button button = new Button("Button");
pane = new Pane();
pane.getChildren().add(button);
stage.setTitle("Test");
scene = new Scene(pane, 640, 640);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
I think there is the idea of binding. But I don't know how to use that, in order to make all nodes of a pane resizable, when the stage size is changing.
I'm searching a solution without Fxml or sceneBuilder.
Thank you in advance.
If you insists to use the Pane container then after the line scene = new Scene(pane, 640, 640); add this:
scene.widthProperty().addListener((c,o,n)->button.setPrefWidth((Double)n));
scene.heightProperty().addListener((c,o,n)->button.setPrefHeight((Double)n));
and after the line stage.setScene(scene); add this:
button.setPrefSize(scene.getWidth(), scene.getHeight());
This works fine with Pane and do your required thing.
But I prefer using an AnchorPane container and set the Top, Right,Bottom and Left anchors to 0 .
Here is the solution if you wish to bind the width of the button to you scene width
button.minWidthProperty().bind(scene.widthProperty());
You can also modify this +/- whatever you want for ex
button.minWidthProperty().bind(scene.widthProperty().subtract(20));
and you can do the same for the height
button.minHeightProperty().bind(scene.heightProperty().subtract(200));

JAVAFX binding imageview on button(responsive)

Here i would like to create a responsive button alongwith imageview,but the problem is imageview not binding properly with button and if i clicked on the button or try to resize the window, automatically the image size increeses and lot of irrelevent scaling problems occuring,eventhough i have'nt set an eventhandler for that button.
This is my sample code
public class ImageController extends Application{
private DoubleProperty fontSize = new SimpleDoubleProperty(10);
#Override
public void start(Stage primaryStage) {
FlowPane fp=new FlowPane(); //here i used flowpane to make imagegallery(productview) that will be in responsive in thier position and i tested my problem not with the flowpane
for(int j=0;j<1;j++)
{
try {
Button button = new Button();
button.styleProperty().bind(Bindings.concat("-fx-font-size: ", fontSize.asString(), ";")); //button size binded to the scene
FileInputStream input = new FileInputStream("images/wine.png");
Image image = new Image(input, 100, 100, true,true);
ImageView imageView=new ImageView(image);
imageView.setPreserveRatio(true);
imageView.fitWidthProperty().bind(button.widthProperty()); //image size binded to the button
imageView.fitHeightProperty().bind(button.heightProperty());
button.setGraphic(imageView);
fp.getChildren().add(button);
} catch (FileNotFoundException ex) {
Logger.getLogger(ImageController.class.getName()).log(Level.SEVERE, null, ex);
}
}
Scene scene = new Scene(fp, 500, 500);
fontSize.bind(scene.widthProperty().add(scene.heightProperty()).divide(50));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
you can see my problem dairectly by running my code and resize the window or clicking on button.I need a button alongwith imageview both will resize according to screen resize(responsive)that's all.ThankYou in advance

javafx 8 overlapping layers eventhandling

I have two layers in my program with different elements in each layer. The two layers are overlapping but the elements in the layers are not. I want to show a tooltip when the mouse hovers over a node in each layer but right now the top layer only gets the event.
Below is attached a minimal example:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
StackPane root = new StackPane();
Pane p1 = new Pane();
Pane p2 = new Pane();
Arc arc = new Arc(150,150,100,100,0,360);
arc.setType(ArcType.CHORD);
arc.setFill(null);
arc.setStroke(Color.BLUE);
arc.setStrokeWidth(20);
Rectangle rectangle = new Rectangle(100,100);
rectangle.setX(100);
rectangle.setY(100);
Tooltip.install(arc, new Tooltip("Semiring"));
Tooltip .install(rectangle,new Tooltip("Rectangle"));
p1.getChildren().add(arc);
p2.getChildren().add(rectangle);
root.getChildren().addAll(p2,p1);
primaryStage.setScene(new Scene(root, 300, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Nothing happens on the rectangle
Use
p1.setPickOnBounds(false);
This essentially means mouse events are only delivered to p1 if the mouse is over a non-transparent pixel in p1. Thus when the mouse is not over the arc, mouse handling is delegated to p2, as required.

How can I assign an EventListener to a Path in javafx?

I have this piece of code which doesn't work correctly.
I want to set a listener for when a user clicks inside the square, yet
neither the pop-up nor the message "clicked" are displayed when I click
inside the square.
What am I missing?
This method is inside the Coords class.
public static void drawMyShape(final GraphicsContext ctx) {
Path path = new Path();
MoveTo mT = new MoveTo();
LineTo lT[] = new LineTo[4];
mT.setX(200.0);
mT.setY(200.0);
lT[0] = new LineTo(400.0, 200.0);
lT[1] = new LineTo(400.0, 400.0);
lT[2] = new LineTo(200.0, 400.0);
lT[3] = new LineTo(200.0, 200.0);
path.setStroke(Color.BEIGE);
path.getElements().addAll(mT, lT[0], lT[1], lT[2], lT[3]);
path.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(Main.prim_stage);
VBox box = new VBox(20);
box.getChildren().add(new Text("Hey"));
Scene s = new Scene(box, 300, 200);
dialog.setScene(s);
dialog.show();
System.out.println("Clicked");
}
});
ctx.setLineWidth(4.0);
ctx.beginPath();
ctx.moveTo(mT.getX(), mT.getY());
for (int i = 0; i < lT.length; i++) {
ctx.lineTo(lT[i].getX(), lT[i].getY());
}
ctx.closePath();
ctx.stroke();
}
EDITED ON SUGGESTION by users.
So his is the main program:
public class Main extends Application {
public static Pane root;
private static Canvas main_canvas;
private static GraphicsContext ctx;
private static Rectangle2D bounds;
private static Scene scene;
public static Stage prim_stage;
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Switzerland Advertising");
initElements(primaryStage);
Coords.drawMyShape(ctx);
primaryStage.show();
System.out.println("Launched");
}
public static void main(String[] args) {
launch(args);
}
}
Everything is instanciated inside the following function, which works correctly and displays a full screen application with a canvas and a square drawn into it (image at the bottom).
private void initElements(final Stage primaryStage) {
prim_stage = primaryStage;
// ----------------------------------------
bounds = Screen.getPrimary().getVisualBounds();
double w = bounds.getWidth();
double h = bounds.getHeight();
// ----------------------------------------
// init elements of scene
root = new Pane();
main_canvas = new Canvas(w, h);
// ----------------------------------------
// init scene elements
scene = new Scene(root, w, h);
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setWidth(w);
primaryStage.setHeight(h);
primaryStage.setScene(scene);
// ----------------------------------------
ctx = main_canvas.getGraphicsContext2D();
// set elements in main pane
root.getChildren().add(main_canvas);
// ----------------------------------------
}
So how can I make the pop-up window appear whenever I click inside the region drawn on the canvas?
This is the program
Your path is just a local variabl within your method. It has to be attached to the scene graph in order to get events. But when you attach it to the scene graph, drawing the same path on a canvas also does not make much sense.

Resources