Attempting to use a JavaFX StackPane's snapshot method to capture a "Background" element. I'm specifically interested in a node's background (as the name suggests).
If I setup my scene with a StackPane, and the background literally being an ImageView underneath what I'm trying to display, then everything works fine. But if I use the more intuitive setBackground function of a node, and try to capture a snapshot, it (the background) doesn't show up.
For example this works as expected, if you do getBackgroundNode().snapshot(new SnapshotParameters(), null):
private Node getBackgroundNode() {
ImageView background = new ImageView(new Image("https://www.yamaha-motor.ca/images/pages/products/units/MC/action/2016_FZ_07_2_l.jpg"));
Rectangle2D viewport = new Rectangle2D(0, 0, 1080, 720);
background.setViewport(viewport);
return background;
}
However, the below method doesn't show me the background when I call the snapshot method.
private Node getBackgroundNode() {
Image background = new Image("https://www.yamaha-motor.ca/images/pages/products/units/mc/action/2016_fz_07_2_l.jpg");
StackPane stack = new StackPane();
stack.setBackground(new Background(new BackgroundImage(background, null, null, null, null)));
stack.setPrefSize(1080, 720);
return stack;
}
Is this simply a feature of the snapshot method? I took a look at SnapshotParameters and there aren't any obvious settings that would allow me to capture the background.
The size of a StackPane is usually not set until it has been layouted. Therefore you create a snapshot of a Node of size (0, 0). A properly layouted Node includes the background. You could set the size of the StackPane by calling resize before taking the snapshot:
Node backgroundNode = getBackgroundNode();
backgroundNode.resize(1080, 720);
backgroundNode.snapshot(new SnapshotParameters(), null);
Related
The problem I'm having is adding a button to the scene and still maintain the original color of the scene. I have created the scene originally black but when adding the button it becomes white. Do any of you know how to fix this issue?
#Override
public void start(Stage teater) {
teater.setTitle("Adventure Game");
Circle circle = new Circle(200, 100, 30);
circle.setFill(Color.WHITE);
Text text = new Text(Integer.toString(resultat));
text.setFont(Font.font("Calibri", 25));
text.setFill(Color.BLACK);
StackPane root = new StackPane(circle, text);
root.setLayoutX(165);
root.setLayoutY(90);
Text text1 = new Text(50, 40, "Adventure Game");
text1.setFont(Font.font("Edwardian Script ITC", 50));
text1.setFill(Color.WHITE);
Button button = new Button("Avslutt");
button.setTextFill(Color.WHITE);
button.setLayoutX(10);
VBox vBox = new VBox(text1, root);
Pane pane = new Pane(vBox);
pane.setLayoutX(50);
pane.setLayoutY(0);
Scene scene = new Scene(pane, 400, 200, Color.BLACK);
Without button:
With button:
It's not the scene that is changing its background color, but the root of the scene, which is having the styles defined in the default modena.css style sheet applied.
Note that CSS is not applied unless an instance of Control (or one of its subclasses, like Button) is created: the idea here is that styles are mainly defined only for controls, so it's not worth the performance hit for applications that use no controls (purely graphical applications, etc). There is no need to even add the control to the scene graph: as soon as Control's constructor is called, the stylesheet will be applied.
A quick fix is
pane.setStyle("-fx-background-color: transparent ;");
or
pane.setStyle("-fx-background-color: black ;");
but it's probably better to define an external stylesheet:
.root {
-fx-background: black ;
}
as you'll likely find there are other styles you want to control (in fact, with a little work, you can move all the font and color definitions to the CSS file giving your code better separation).
I'm approaching to develope a Snake Game with JavaFX (I'm benniger).
In the main method I have set scene.setFill(Color.BLACK) and so the background is totally black. When I add a Label, when I try to instantiate it, the background disappear and the Label is not shown on the screen.
It does not happen if I add Rectangle or Circle, but only with Labels, Buttons ecc.
How can I do to solve this? I think it is a simple question but I can not solve it by myself.
/Main.java
GamePanel g = new GamePanel();
BorderPane root = new BorderPane();
//Scene scene = new Scene(root,400,400, Color.BLACK);
Scene scene = new Scene(root,400,400);
scene.setFill(Color.BLACK);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setTitle("SnakeFX");
primaryStage.show();
root.getChildren().add(g);
g.requestFocus();
/GamePanel.java (I put only a part of the function initialize() that
is the first function of the constructor and that initialize the
gamegraphics and that must contain my label)
void initialize() {
/* IF I PUT THIS LINE THE BLACK COLOR ON THE BACKGROUND DISAPPEAR
AND LABEL DOES NOT APPEAR ON THE SCREEN.
WITHOUT THIS LINE THE GAME RUNS PERFECTLY B BUT I NEED THIS LINE TO ADD
THE SCORE EHEH */
Label l = new Label("TEST"); //this is the line
for(int i=0;i<WIDTH;i=i+WIDTH/40) {
Line line = new Line();
line.setStartX((double)i);
line.setStartY(0.0);
line.setEndX((double)i);
line.setEndY((double)HEIGHT);
line.setVisible(true);
super.getChildren().add(line);
}
for(int j=0;j<HEIGHT;j=j+HEIGHT/40) {
Line line = new Line();
line.setStartY((double)j);
line.setStartX(0.0);
line.setEndY((double)j);
line.setEndX((double)WIDTH);
line.setVisible(true);
super.getChildren().add(line);
}
....
...
. ..
}
First image is without the instantiation of the label.
Second image is with the instantiation of the label (The background color is not shown and the label is not shown)
This is a JavaFx bug (see this answer).
What you see in your second image is the root node's (BorderPane) background color (which is defined in javafx default theme and it's not transparent). This is the correct state - the first image shows the bug described in the answer linked above.
You can fix your problem easily:
remove the background color from the root node, so the scene's background color becomes visible:
root.setBackground(Background.EMPTY);
or, set the root node's background color to black:
root.setBackground(new Background(new BackgroundFill(Color.BLACK, null, null)));
How would I be able to set the background image to the size of the window when increasing or decreasing the window frame? Right now the image is a set size of 300,300 so when increasing the window the size stays the same.
Here's a snippet of my code:
grid.getChildren().addAll(nameLabel, nameInput, passLabel, passInput,
loginButton);
grid.setMinSize(300,300);
grid.setMaxSize(300,300);
StackPane root = new StackPane(grid);
NumberBinding maxScale = Bindings.min(root.widthProperty().divide(300),
root.heightProperty().divide(300));
grid.scaleXProperty().bind(maxScale);
grid.scaleYProperty().bind(maxScale);
BackgroundImage myBI= new BackgroundImage(new Image("image.jpg", 300, 300,
false, true),
BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT,
BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT);
//then you set to your node
grid.setBackground(new Background(myBI));
Scene scene = new Scene(root, 300,300);
window.setScene(scene);
window.show();
You can try to instantiate a BackgroundSize object according to documentation and set the cover value to true. Then instead of using BackGroundSize.DEFAULT, use the BackGroundSize object you created.
I am trying to create a textfield that has an image part within itself, similar to this.
imageView.fitHeightProperty().bind(Bindings.createDoubleBinding(
() -> textField.getHeight() -
textField.getPadding().getTop() -
textField.getPadding().getBottom(),
textField.heightProperty(), textField.paddingProperty()));
imageView.fitWidthProperty().bind(imageView.fitHeightProperty());
textField.paddingProperty().bind(Bindings.createObjectBinding(
() -> new Insets(textField.getPadding().getTop(),
textField.getPadding().getRight(),
textField.getPadding().getBottom(),
textField.getPadding().getRight() * 2 + imageView.getFitWidth()),
imageView.fitWidthProperty(), textField.paddingProperty()));
My current approach is to use a StackPane to hold the TextField, then also add an ImageView as the StackPane's child. The ImageView needs to know how resize itself, so I have bound its fitHeight to the TextField's height, with consideration of the TextField's padding.
The ImageView's fitWidth is then bound to its own fitHeight.
Lastly, I need to make my TextField's text offset to the right (because the image is blocking it), so I once again did another binding that is dependent on the ImageView's fitWidth.
This ends up with circular dependency, which causes the stack to overflow. Is there any other way to do it without hard coding the TextField's left padding?
Here is a little exemple, i've used (StackPane/TextField/ImageView) but instead of the Image i advise you to draw your own shape with SVG to have the full control on it (MouseHover/Focused...), i've also used a CSS to achieve this :
Java :
private StackPane sp = new StackPane();
private TextField tf = new TextField();
private ImageView iv;
//Init StackPane
sp.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
sp.getStyleClass().add("identifiant");
sp.setPrefSize(200, 40);
sp.setLayoutX(100);
sp.setLayoutY(100);
//Init ImageView
iv = new ImageView(getClass().getResource("Img.png").toString());
StackPane.setAlignment(iv, Pos.CENTER_LEFT);
StackPane.setMargin(iv, new Insets(0, 0, 0, 10));
//Init TextField
StackPane.setAlignment(tf, Pos.CENTER_LEFT);
StackPane.setMargin(tf, new Insets(2, 5, 0, 30));
//Add all content
sp.getChildren().addAll(iv,tf);
Css :
.identifiant{
-fx-background-color:#45444a;
-fx-effect:innershadow(three-pass-box , rgba(0,0,0) , 6, 0.0 , 0 , 0);
-fx-background-radius:8px;
}
.text-field{
-fx-background-insets:0;
-fx-background-color:#45444a;
-fx-text-fill:white;
}
Hope this will help you !
I use the snapshot() method on the Shape object in order to convert it into ImageView and nest it into Label. The problem is, that when I take a snapshot of the Shape object it is closed into square field with white background. Is there a way to make it transparent? I use the code below in order to convert given Shape into an ImageView object:
WritableImage snapshot = Shape.snapshot(new SnapshotParameters(), null);
ImageView imageView = new ImageView(snapshot);
Label label = new Label();
label.setGraphic(imageView);
Pane.getChildren().add(label);
Here you go
SnapshotParameters parameters = new SnapshotParameters();
parameters.setFill(Color.TRANSPARENT);
WritableImage snapshot = shape.snapshot(parameters, null);
...