Javafx How To Set Background Image
Ofttimes, you don't desire to settle for the Os-dependant background most JavaFX applications default to. Luckily, JavaFX is incredibly flexible in the way it allows developers to set their backgrounds as images, colors, gradients, and patterns.
Because of the way JavaFX layers its applications from the Stage upwards, there are multiple ways to set backgrounds. In fact, multiple Background fills and colors tin exist blended using transparency, creating a really rich user feel.
The simplest way to prepare the JavaFX Scene background color or image is by invoking the Scene
's setFill()
method, which can accept a color, slope or image pattern. A more than flexible way to set the background of a scene is to set the root node's background, which tin can accept multiple images and fills. This can be done in both Java code and past using CSS.
As a special case, you can also set the Scene to exist completely transparent. In that instance, you'll need to set the Stage as transparent, because by default this is filled with an off-white color:
Over the course of this article, I'll go through each in depth.
What you'll get from this article:
One of JavaFX's greatest strengths (and weaknesses…) is the number of means it lets you exercise things.
In the case of the app background, there are two means – using the Scene object and the root node of the scene graph (that's all the nodes in the scene).
This article goes through every mode to do it, from the simplest (setting information technology on the Scene itself) to the most flexible (setting it on the root node using CSS):
- Setting the background of the Scene object itself
- Setting the background of the Scene's root node (much more flexible!)
- Creating a completely transparent Stage.
When to use each: If you're wondering when to use each of these options, hither's a quick idea:
Element | Capability | Benefits | Limitations |
---|---|---|---|
Scene | Single color, gradient or image pattern. | Fix in a single place when using dynamic scene graph | Can only be prepare in Java code (not CSS) |
Root Node | Multiple images, fills, gradients and patterns | Complex, rich backgrounds created on a unmarried node (region) | Tin can only be used if the root node is a Region (Cannot be set on a Group) |
CSS Vs Coffee Code: You can set backgrounds on the root node (and in fact any Region
!) using both CSS and Java code. I massively favour doing it using CSS, because it's more concise, you can automate it through attributes in the FXML, and there are a lot more than utility values you tin dip into. However, there are instructions and comparisons on how to practice both in lawmaking examples below.
Overall, JavaFX provides some flexible and robust ways to fill your scenes with content that brand for a rich user feel without needing to cramp the scene graph with ImageView and Canvas objects.
Here's an example of an animated background created using only 1 VBox as a root node, and 6 layered background images:
Lines of code used:
Coffee: | 14 |
CSS: | 4 |
FXML: | 1 |
Total: | 19 |
The lawmaking for this is correct here.
Setting the background of the Scene object
The scene itself tin have a groundwork, which can be ready by invoking setFill(Colour color)
on the scene object itself, passing in the Colour
object you desire to utilize.
The setFill()
method just accepts a single Paint
object, which means you cannot use this method to create layered furnishings. Nor can you set images equally a background, with the exception of the ImagePattern
object, which extends Pigment
.
Past default, all the layout panes to a higher place that make upwards your scene are transparent, so the absolute simplest way to set the background colour of a Scene is to use this method.
That single Paint
value can be a gradient, or image blueprint, simply you can only specify 1.
Here's how to practise each:
1. Color
You can yet create visually appealing apps with just a single flat color. To do this, you lot can use either i of the default named colors such as Colour.RED
, or you tin can create a color using one of the supplied functions.
Available functions:
//Constructors available: new Colour colour(double red, double green, double bluish); //Static functions available: Color.rgb(int cherry, int green, int blue, double opacity); Color.rgb(int red, int greenish, int blue); Color.hsb(double hue, double saturation, double brightness, double opacity); Color.hsb(double hue, double saturation, double brightness); Colour.spider web(Cord colorString, double opacity); Color.web(String colorString); // I won't include all the 'gray' static methods hither...
Example:
scene.setFill(Color.web("#81c483"));
2. Linear Slope
If you lot need a dissimilar expect, you can too create a linear gradient past passing a LinearGradient
object to the setFill()
method. Unlike in CSS, there'southward no defaults, so we need to specify all positional, cycling and color stop arguments in series.
Available functions:
//Constructors available: new LinearGradient( double startX, double startY, double endX, double endY, boolean proportional, CycleMethod cycleMethod, Terminate... stops); new LinearGradient( double startX, double startY, double endX, double endY, boolean proportional, CycleMethod cycleMethod, Listing<End> stops); //Static functions available: LinearGradient.valueOf(String value); //accepts CSS String.
Example:
scene.setFill(new LinearGradient( 0, 0, 1, 1, true, //sizing CycleMethod.NO_CYCLE, //cycling new Stop(0, Color.web("#81c483")), //colors new Stop(1, Colour.web("#fcc200"))) );
ii. Radial Gradient
Or, you could create a radial gradient using the RadialGradient
object. Again, this is not the most concise to ascertain.
Bachelor functions:
//Constructors available: new RadialGradient( double focusAngle, double focusDistance, double centerX, double centerY, double radius, boolean proportional, CycleMethod cycleMethod, Stop... stops) new RadialGradient( double focusAngle, double focusDistance, double centerX, double centerY, double radius, boolean proportional, CycleMethod cycleMethod, List<Stop> stops) //Static functions available: RagialGradient.valueOf(String value); //accepts CSS String.
Example:
scene.setFill(new RadialGradient( 0, 0, 0, 0, 1, true, //sizing CycleMethod.NO_CYCLE, //cycling new Stop(0, Color.web("#81c483")), //colors new Terminate(i, Color.spider web("#fcc200"))) );
Limitations: In that location are limitations to setting the background of your app directly on the Scene object:
- Information technology must exist set in Java code
- It cannot exist automated through the FXML file
- Information technology's non very concise (no defaults similar in CSS)
For that reason, I normally set my backgrounds on the root node of my scene. Because layouts naturally stretch to fit their container (the Scene), this ordinarily has the same effect.
I choose to do it with CSS considering I observe it more concise and convenient, simply I've shown both ways below so you can decide.
Setting Backgrounds of your root nodes:
A much more than flexible approach to setting backgrounds is to apply them to the root node.
Considering the JavaFX scene graph sits on superlative of the Scene
and Stage
objects, any fills or images practical to your root nodes volition paint over the Scene
anyway.
For these situations, CSS is 100% my recommended method. It'south more succinct, there are a significant number of useful defaults you lot can make employ of. That being said, you can achieve the same results using pure Java too.
It just takes a little longer.
Backgrounds can be ready as both images and fills (colors and gradients). So this section will be carve up according to how you want to set the groundwork.
Click the links to leap to the section you need, or but read all the mode through for both.
Warning: Non all root nodes volition expand to fill the Scene past default. For example the GridPane
, will by default not stretch to fit its container.
If you lot want more details on how each Layout works, bank check out the JavaFX Layouts guide I've put together here.
So, assuming you're using a layout pane that expands to fill up the Scene, nosotros can use background images to paint across the entire window.
Setting Background Images in JavaFX
A actually efficient way to fix the groundwork of the JavaFX scene is by using images. These tin can exist assault any Region object, so if you set them on the root node (assuming it'south a Region
non a Group
), you can utilise them as the base layer of your Scene.
The Groundwork paradigm, or images, of the root node tin be fix using CSS using the -fx-background-image
JavaFX CSS holding. Alternatively, information technology tin be set by invoking the setBackground()
method on the root node in Java lawmaking, although this is more often than not less concise.
Any number of images can be used, and will be rendered in the order they're specified, meaning you tin layer upward your images like this:
That'southward a great fashion to add some drama to your scene without having to worry most multiple ImageViews to hold all those images.
Here's what nosotros'll be working towards in this section. I'll go over how to consummate this using both CSS and a Java-simply approach.
Comparison of Coffee-only and CSS approaches:
Below are coded examples of how to create the to a higher place Scene using background images both with and without CSS.
In this example, using CSS saves a significant amount of lawmaking, utilising FXML to create the scene graph, and CSS defaults to create concise code.
Java only:
Lines of code used:
Java: | 37 (23)* |
CSS: | 0 |
FXML: | 0 |
Full: | 37 (23) |
Coffee & CSS:
Lines of code used:
Java: | five* |
CSS: | eleven |
FXML: | ane |
Total: | 17 |
Setting Background Images using CSS
Setting background images using JavaFX's CSS syntax is my suggested approach. It has the post-obit benefits over hardcoding it in Java:
- The CSS syntax itself has a lot of useful default values not available in Java code, significant it'south nigh always more than curtailed.
- The reference to the CSS file can exist coded into your FXML document, and so you lot don't need to manually adhere it.
- The behaviour of the scene graph is automatically delegated to the Controller (tin also be set in FXML), allowing complex behaviour to be encapsulated abroad from other code
To achieve the effect higher up, nosotros'll demand to create a View using FXML. Considering it's such a simple scene graph (1 node) we strictly only need ane line of code.
<VBox stylesheets="@../css/styles.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"/>
Then, inside the CSS file styles.css
, we tin define the background images, too equally the size, position and echo-behaviour of the images.
Really worth noting the CSS defaults we're making the use of here: contain
, bottom
and repeat-x
, all of which hateful nosotros tin can ascertain our image behaviour in a really pocket-sized amount of code.
.root{ -fx-background-size: contain, incorporate, contain, contain, contain, contain; -fx-groundwork-position: bottom, bottom, bottom, lesser, bottom, bottom; -fx-background-repeat: repeat-x, repeat-x, repeat-x, repeat-x, repeat-10, echo-x; -fx-groundwork-prototype: url("https://edencoding.com/wp-content/uploads/2021/03/layer_06_1920x1080.png"), url("https://edencoding.com/wp-content/uploads/2021/03/layer_05_1920x1080.png"), url("https://edencoding.com/wp-content/uploads/2021/03/layer_04_1920x1080.png"), url("https://edencoding.com/wp-content/uploads/2021/03/layer_03_1920x1080.png"), url("https://edencoding.com/wp-content/uploads/2021/03/layer_02_1920x1080.png"), url("https://edencoding.com/wp-content/uploads/2021/03/layer_01_1920x1080.png"); }
Images are specified equally a URL (see my JavaFX CSS guide here for more information). These tin be both local and online files – I've made these bachelor online and then you can but copy and paste that CSS lawmaking without worrying where they are in your project structure.
On height of that, because the code is so concise, we tin can brand the most of information technology to add functionality.
Animating Backgrounds using CSS:
One additional benefit of coding this with CSS is the ease with which y'all can individually alter the background position using in-line styles for the -fx-background-position
JavaFX CSS holding.
To practise this, nosotros'll need to add an fx:id
attribute and a controller to the FXML file:
<VBox xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:id="content" fx:controller="com.edencoding.controllers.ExampleController" stylesheets="@../css/styles.css"> </VBox>
And so, by creating a Controller using but a few lines of code, nosotros can shift each background prototype by different amounts each frame.
public grade ExampleController { public Region content; public void initialize() { DoubleProperty xPosition = new SimpleDoubleProperty(0); xPosition.addListener((observable, oldValue, newValue) -> setBackgroundPositions(content, xPosition.get())); Timeline timeline = new Timeline( new KeyFrame(Elapsing.ZERO, new KeyValue(xPosition, 0)), new KeyFrame(Duration.seconds(200), new KeyValue(xPosition, -15000)) ); timeline.play(); } void setBackgroundPositions(Region region, double xPosition) { String style = "-fx-background-position: " + "left " + xPosition/6 + "px bottom," + "left " + xPosition/5 + "px bottom," + "left " + xPosition/4 + "px bottom," + "left " + xPosition/3 + "px bottom," + "left " + xPosition/ii + "px bottom," + "left " + xPosition + "px bottom;"; region.setStyle(fashion); } }
I call up information technology creates a pretty interesting parallax groundwork upshot.
In this instance, it'south an example I've taken right out of a JavaFX CSS reference I'm edifice. Specifically, the example in the entry for -fx-background-image.
Setting background images without CSS
Setting background images with Java lawmaking is a trivial less pretty, but considering every CSS holding is backed by a JavaFX object, we can nevertheless do it without many bug.
If we want to do this entirely in Java code – without a controller – we tin just create the VBox in our Application's start()
method just before we show the Stage.
Then, we tin set the Background object of the content
Region
. In doing so, we'll pass in a series of BackgroundImage
objects. Each BackgroundImage
will need to be defined in total, as in that location are no useful presets for Coffee-only code.
public class App extends Application { @Override public void start(Stage stage) throws Exception { VBox content = new VBox(); content.setBackground(new Background( new BackgroundImage( new Image("https://edencoding.com/wp-content/uploads/2021/03/layer_06_1920x1080.png"), BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, new BackgroundPosition(Side.LEFT, 0, true, Side.BOTTOM, 0, true), new BackgroundSize(BackgroundSize.Automobile, BackgroundSize.Auto, truthful, true, false, true) ), new BackgroundImage( new Paradigm("https://edencoding.com/wp-content/uploads/2021/03/layer_05_1920x1080.png"), BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, new BackgroundPosition(Side.LEFT, 0, true, Side.BOTTOM, 0, true), new BackgroundSize(BackgroundSize.AUTO, BackgroundSize.AUTO, true, truthful, false, true) ), new BackgroundImage( new Epitome("https://edencoding.com/wp-content/uploads/2021/03/layer_04_1920x1080.png"), BackgroundRepeat.Echo, BackgroundRepeat.NO_REPEAT, new BackgroundPosition(Side.LEFT, 0, true, Side.Bottom, 0, true), new BackgroundSize(BackgroundSize.AUTO, BackgroundSize.AUTO, true, truthful, simulated, true) ), new BackgroundImage( new Prototype("https://edencoding.com/wp-content/uploads/2021/03/layer_03_1920x1080.png"), BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, new BackgroundPosition(Side.LEFT, 0, truthful, Side.BOTTOM, 0, truthful), new BackgroundSize(BackgroundSize.Automobile, BackgroundSize.AUTO, true, true, false, true) ), new BackgroundImage( new Image("https://edencoding.com/wp-content/uploads/2021/03/layer_02_1920x1080.png"), BackgroundRepeat.Echo, BackgroundRepeat.NO_REPEAT, new BackgroundPosition(Side.LEFT, 0, true, Side.Lesser, 0, true), new BackgroundSize(BackgroundSize.AUTO, BackgroundSize.AUTO, truthful, truthful, false, true) ), new BackgroundImage( new Prototype("https://edencoding.com/wp-content/uploads/2021/03/layer_01_1920x1080.png"), BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, new BackgroundPosition(Side.LEFT, 0, true, Side.BOTTOM, 0, true), new BackgroundSize(BackgroundSize.Car, BackgroundSize.AUTO, true, true, false, true) )) ); Scene scene = new Scene(content, 800, 450); stage.setScene(scene); stage.getIcons().add together(new Prototype(getClass().getResourceAsStream("/com/edencoding/img/EdenCodingIcon.png"))); stage.setTitle("Scene Groundwork"); stage.setScene(scene); stage.show(); } }
We can make this more concise by creating a utility role to deal with the fact that nosotros're unable to claw into the CSS defaults.
public class App extends Application { @Override public void start(Stage stage) throws Exception { VBox content = new VBox(); content.setBackground(new Background( createImage("https://edencoding.com/wp-content/uploads/2021/03/layer_06_1920x1080.png"), createImage("https://edencoding.com/wp-content/uploads/2021/03/layer_05_1920x1080.png"), createImage("https://edencoding.com/wp-content/uploads/2021/03/layer_04_1920x1080.png"), createImage("https://edencoding.com/wp-content/uploads/2021/03/layer_03_1920x1080.png"), createImage("https://edencoding.com/wp-content/uploads/2021/03/layer_02_1920x1080.png"), createImage("https://edencoding.com/wp-content/uploads/2021/03/layer_01_1920x1080.png") ) ); Scene scene = new Scene(content, 800, 450); stage.setScene(scene); stage.getIcons().add(new Image(getClass().getResourceAsStream("/com/edencoding/img/EdenCodingIcon.png"))); stage.setTitle("Scene Background"); phase.setScene(scene); phase.show(); } private static BackgroundImage createImage(Cord url) { return new BackgroundImage( new Image(url), BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, new BackgroundPosition(Side.LEFT, 0, true, Side.BOTTOM, 0, true), new BackgroundSize(BackgroundSize.AUTO, BackgroundSize.AUTO, true, truthful, false, true)); } }
Again, I've included online references to the required pictures so you should exist able to copy-and-paste the code. Nevertheless, the files can also exist stored locally in your project.
Just remember any style changes throughout your application will have to exist changed at the Java source, rather than using a key stylesheet.
Overall, I think this is a less make clean mode to accomplish our goal, but it will have the same effect.
Setting Background Colors and Fills in JavaFX
Often, y'all don't want or need images as a background to your app. In fact, more frequently, you may only want to set up a single gradient.
Groundwork colors, gradients and prototype patterns of the root node can be set using the -fx-background-colour
JavaFX CSS holding on the root element. Alternatively, information technology can be set by invoking the setBackground()
method on the root node in Java code, although this is generally less concise.
Here'due south what we'll be working towards in this section. It actually includes three layers:
- A linear gradient of blue to pink (top to bottom)
- An image pattern (in this case providing stars)
- A radial slope going from white to black, with transparency, to provide a vignette result
Comparing of Java-only and CSS approaches:
Below are coded examples of how to create the above Scene using background images both with and without CSS.
Again, using CSS saves a significant amount of code, utilising FXML to create the scene graph, and CSS defaults and utility functions to create concise code.
Coffee merely:
Lines of code used:
Coffee: | 31* |
CSS: | 0 |
FXML: | 0 |
Total: | 31 |
Coffee & CSS:
Lines of code used:
Coffee: | 5* |
CSS: | 3 (ane)** |
FXML: | ane |
Total: | ix (7) |
**Tin can be coded on ane line. Separated for clarity in code blocks beneath.
Setting Background Colors and Fills using CSS
As with the background images, for this scene we'll need the simplest View – a VBox as the root node, so it will stretch to the size of the container.
Nosotros tin can write this in a single line of XML code, although I will separate the stylesheets attribute onto a divide line so it'southward easier to encounter.
<VBox xmlns="http://javafx.com/javafx/10.0.2-internal" stylesheets="@../css/styles.css"/>
At present, we tin include the linear gradient, repeating paradigm pattern and radial gradients we need in a really concise way within the CSS file.
Really worth noticing here the JavaFX CSS parser understands the default linear gradient proceeds from top to bottom, so we need merely specify the colors. Also the repeating-prototype-design() function provides a 1-parameter function to specify our stars!
.root{ -fx-background-color: linear-gradient(#4568DC, #B06AB3), repeating-image-pattern("https://edencoding.com/resource/wp-content/uploads/2021/02/Stars_128.png"), radial-slope(center l% 50%, radius fifty%, #FFFFFF33, #00000033); }
The repeating-prototype-pattern() office accepts both local and online files, but I've specified it as an online file I'one thousand hosting myself so you tin can simply copy and paste that lawmaking.
Setting Background Colors and Fills Without CSS
If we're creating this using only JavaFX lawmaking, we can create our VBox and add the groundwork fills purely from within our Coffee code without the demand for FXML.
public class App extends Application { @Override public void start(Stage stage) throws Exception { VBox content = new VBox(); content.setBackground(new Background( new BackgroundFill( new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, new End(0, Color.web("#4568DC")), new Stop(one, Color.web("#B06AB3")) ), CornerRadii.EMPTY, Insets.EMPTY ), new BackgroundFill( new ImagePattern( new Paradigm("https://edencoding.com/resources/wp-content/uploads/2021/02/Stars_128.png"), 0, 0, 128, 128, false ), CornerRadii.EMPTY, Insets.EMPTY ), new BackgroundFill( new RadialGradient( 0, 0, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE, new End(0, Colour.web("#FFFFFF33")), new Stop(1, Color.web("#00000033"))), CornerRadii.EMPTY, Insets.EMPTY ) )); Scene scene = new Scene(content, 800, 450); phase.setScene(scene); stage.getIcons().add together(new Epitome(getClass().getResourceAsStream("/com/edencoding/img/EdenCodingIcon.png"))); phase.setTitle("Scene Background"); stage.setScene(scene); phase.show(); } }
The benefit of this is that we tin create a actually simple one-class program, which should run out of the box. However, none of the behaviour is outsourced to a Controller, and any style changes volition need to be hard-lawmaking applied later.
Nevertheless, it does attain the aforementioned issue.
Creating a transparent Scene in JavaFX
Sometimes, especially when you're creating a completely custom view, y'all often want your Phase to be transparent.
When y'all're aiming to create a fully transparent view in JavaFX, it's admittedly worth remembering that the root node is rendered above 2 other layers of JavaFX window infrastructure – the Phase and the Scene object itself.
In JavaFX, the Scene can exist made transparent past invoking setFill(Color.TRANSPARENT)
on the Scene
object, and initStyle(StageStyle.TRANSPARENT)
on the underlying Phase
object. Annotation that StageStyle.TRANSPARENT
volition also remove windowing features such as the minimise and shut buttons.
In this example, we'll create a really simple view using FXML:
<VBox xmlns="http://javafx.com/javafx/ten.0.two-internal" xmlns:fx="http://javafx.com/fxml/one" alignment="Center" spacing="25.0" stylesheets="@../css/styles.css" > <Label text="Transparent App Window" /> <ImageView> <Image url="@../img/EdenCodingIcon.png" /> </ImageView> <padding> <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" /> </padding> </VBox>
Here, the mode canvass is not important, but without any styles, nosotros won't be able to see our layout. I've besides added some basic layout attributes to make it a little more pleasant.
I'll keep the CSS simple – a semi-transparent groundwork color, and a border then we can se where the Scene begins and ends.
.content{ -fx-edge-color: black; -fx-border-width: 1px; -fx-background-color: #F3F9F322; }
Finally, we can load our window in the Application start() method, which is too where nosotros'll set the Scene
and Phase
to be transparent.
public form App extends Application { @Override public void first(Stage phase) throws Exception { //Create view FXMLLoader loader = new FXMLLoader(getClass().getResource("fxml/LabelExample.fxml")); Parent root = loader.load(); //Create Scene and fix transparent Scene scene = new Scene(root, 300, 250); scene.setFill(Color.TRANSPARENT); //Set Stage equally transparent and launch stage.initStyle(StageStyle.TRANSPARENT); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
And hither's what it looks like:
Conclusions
JavaFX provides multiple ways to set the background of a Scene, and it can be accomplished in both Coffee code and by using CSS.
Because of the way JavaFX creates the scene graph, it is possible to set the background of the Scene by using either the Scene object itself or – normally – the root node of the Scene graph.
Nevertheless, setting the background on the Scene object itself does have some limitations:
- It must exist set in Java lawmaking
- It cannot be automatic through the FXML file
- It's not very curtailed (no defaults like in CSS)
For a more than flexible arroyo, yous tin can set the background of a layout pane that expands to fit the Scene. This manner, multiple groundwork images and fills can be rendered (and these can even be combined to create scene graphs with images and fills
Combining the approaches above to give the root node both image and pigment backgrounds can produce an even more than dramatic effect.
Javafx How To Set Background Image,
Source: https://edencoding.com/scene-background/
Posted by: leetork1963.blogspot.com
0 Response to "Javafx How To Set Background Image"
Post a Comment