How to add image to image button
How to add image to image button
How to add an image to a button (and position it) in JavaFX
Adding an image to a button can be a great way to improve the user experience – increasing recognisability of button functionality. It also fits with user expectations for touch devices, which are often designed for users with different first languages.
For one reason or other, JavaFX doesn’t make this as easy as it should, although with a few simple steps you can add and position an image.
What’s in this article
What sort of functionality you’ll achieve
JavaFX gives developers a lot of functionality with both adding and positioning buttons in JavaFX.
Here are a few of the simplest layouts possible, which will be covered in this article:
How you’ll do it.
Plus, I’ll show you how to achieve these using Java-only, FXML-only and CSS-only approaches. Read below for more.
How to add an image to a button
The functionality to add an image to a button is actually built into JavaFX! But JavaFX being predictable it’s just not listed as an ‘image’… That’s mostly because the functionality is intended to be more flexible – basically allowing any Node to be added as a ‘graphic’, but the overall effect can be a little confusing.
To set an image on a button, we just need to create an ImageView and add it to the Button using the setGraphic() method of the button object. The usual place to do this is in the initialize() method of the scene’s controller.
Obviously in this example the Java code uses the @FXML annotation you’ll need to reference a Button with the fx:id of button inside the FXML file.
If you want to be able to define the layout entirely in FXML, it’s also possible to set the graphic of a button using the element within the object.
Just make sure to specify the object within the created. That’s usually where it trips me up.
The default graphic position when one isn’t specified is on the left hand side of the text. That gives the button the following general appearance:
If that’s not what you want, we can use the JavaFX ContentDisplay enum to set the image’s position, which is what we’ll do next.
Resources note:
Two important things to note:
Here’s how the code looks. I actually think it’s more concise in a lot of cases than setting it in the Java or FXML code.
Positioning an image inside a button
In JavaFX, the position of a button image can be set using the setContentDisplay() method, passing in the ContentDisplay enum value that represents the desired position of the image. The available ContentDisplay values are TOP, BOTTOM, LEFT, RIGHT and CENTER
In addition to the positional values, the ContentDisplay enum also allows for the values TEXT_ONLY and GRAPHIC_ONLY, which will produce a text and image-only button respectively.
Java/FXML value | CSS value | Visual Appearance |
---|---|---|
TOP | top | |
BOTTOM | bottom | |
LEFT | left | |
RIGHT | right | |
CENTER | center | |
TEXT_ONLY | text-only | |
GRAPHIC_ONLY | graphic-only |
To specify the layout using only FXML code, you’ll need to define the contentDisplay as an attribute of the button object itself. You can do this in one line, or by specifying nested enum objects in your code.
If you want to make the content display more explicit, you can create a element, which confusingly has to contain a nested object that references the enum itself.
This can look a little clumsy, because you end up defining a element with a enum inside it, but it works fine just the same.
Resizing an image with button size
Lastly, if you’re looking at creating a responsive JavaFX application you may need to alter the size of the button image as your app resizes too.
Luckily, it’s really easy to accomplish with a little Java code.
The important lines here are binding the fitWidth property of the ImageView to the button’s read-only width property. Now, when the button size changes, it automatically updates the size of it’s graphic.
Setting the maxWidth of the button is also pretty important. You can set it to any number you want (you may need a maximum size for your button). However, if you don’t set it at all, the button will wrap to the size of the text and graphic and your image will never have a chance to resize.
As with everything JavaFX, you can also do this (at least partly) in FXML. By using the partial support for Expression Binding in FXML, you can perform that binding inside your FXML file.
Unfortunately, complex bindings (like numeric division), aren’t currently supported. However, what we can do is bind the fitHeight property of the ImageView to a property we create ourselves inside the controller.
Honestly, I think this has the benefit of being slightly more elegant, but to be honest, you generate an awful lot of redundant code setting up the property.
Adding an image to a button is supported and relatively simple, but it can be confusing because of the constantly changing names.
Images are really graphics, until you’re trying to position them and then they’re content. Ugh! Here’s a quick summary to get you on the road: