Sometimes you just want to limit a user’s options. If an action isn’t possible, or can’t be completed because of the state of other components in the scene, hiding a button can be a useful way to prompt further user input.

To hide a button in JavaFX, setVisible(false) should be invoked on the button object to remove it from view. The button will still maintain its position and other nodes may still be arranged around it. To uncouple the button from the layout’s position calculations, developers can additionally setManaged(false).

On top of that, you can animate the visibility of your button to remove it from your display in a visually-appealing way. Finally, you can disable a button, to lock it from user input without removing it from the display.

  1. Set the visible property to false.
  2. Set visible and managed properties to false.
  3. Animate the disappearance using transitions.
  4. Disable a button without removing it from display.

I’ll go through each of these one by one and you can work out which one you want to

1. Set the visible property to false.

The simplest way to hide a button from the display is to invoke setVisible() on the button object. Passing the boolean value false will have the effect of making the button completely invisible.

button.setVisible(false);

Buttons that are invisible can’t be interacted with by the user. They won’t respond to input by either the keyboard, or the mouse.

A quick note on performance: Setting the node visibility is much more performance-friendly than manually setting the opacity of an object. Setting the opacity property will cause the background JavaFX rendering logic to re-calculate all the rendering requirements for that node. The setVisible() method is designed to allow developers to rapidly add or remove nodes from view without having to recache the object in the program’s running memory.

Just setting the visible property on a button will remove it from view, but not from the layout. In the following managed layouts, that means objects will still be arranged around your button:

  • TilePane
  • FlowPane
  • HBox and VBox

Sometimes, it will depend on the circumstances:

  • BorderPane, if the button is the only object in a region, and other objects could accommodate that space
  • GridPane, if the button is the only node in a row or column

And sometimes it doesn’t matter at all: in the AnchorPane and StackPane layouts, this won’t make a difference, because each object is positioned individually. For a really thorough breakdown of how every layout pane works, and how to use them, check out my article on JavaFX layouts. It goes into detail about how to choose between different layouts, and how to use them effectively.

if you’re in a situation where objects are still being arranged around your button, and you don’t want that effect, you can also use the setManaged() method to remove it from the layout calculations of the parent node.

2. Set visible and managed properties to false.

On its own, invoking setManaged() on a button inside a layout pane will do two things;

  1. Remove the button from layout calculations, so nodes are not positioned around it
  2. Position the node itself at (0, 0), so it can be positioned manually.

This is actually really useful in some situations, but here we don’t want the button to be visible at all, so we’ll also call setVisible(false) to remove it from view.

button.setVisible(false);
button.setManged(false);

This way, the effect is that it looks like its been removed from the view completely.

A quick note on easy code practices: Obviously, you can get the same effect by physically removing it from the parent object completely. I used to do this, but you have to keep track of whether the button currently in the parent’s children list (or check before you add it). If you’re making something appear and disappear and you unintentionally add it to the parent twice, you’ll throw an IllegalArgumentException.

Caused by: java.lang.IllegalArgumentException: Children: duplicate children added: parent = Pane[id=pane]
	at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:560)
	at javafx.base/com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
	at javafxui/com.edencoding.controllers.PaneTestController.initialize(PaneTestController.java:33)

3. Animate the disappearance using transitions.

Sometimes you just want the user experience to be a little more polished. One part of delivering that can be to animate the way objects like buttons enter and exit the user’s field of view.

From sliding to fading, it’s usually easiest to animate a visible change in a button by using a Transition. That’s a JavaFX animation object designed specifically for Node objects in your Scene.

If you’re interested in learning more about all of JavaFX’s animations, including in-depth information about the Transitions available for nodes, check out my article on animations. It goes into a lot of depth about Timelines, Transitions and the details of how to get the most out of them.

For now, we’ll focus just on animating the opacity of the button.

1. Fading out the button

The great thing about the FadeTransition is that, to make a button disappear, we only need to specify the end opacity (we tell JavaFX we want it to disappear). We don’t need to tell it what opacity to start from – it will by default use the current value.

FadeTransition fadeTransition = new FadeTransition(
        Duration.millis(200), 
        button);
fadeTransition.setToValue(0);
fadeTransition.play();

And that’s it! Our button gone. Before we hit play, though, we might want to set the visibility and managed properties of the button to let other objects in the layout move into the new space we’ve just freed up.

2. Updating

To set a property of the node once the animation has completed, we need to use the transition’s onFinished property, which accepts an EventHandler object. We can define it as a lambda, which makes the code a little more concise.

fadeTransition.setOnFinished(event -> {
    button.setManaged(false);
});

Again, no obligation, but I’ve also made a resource that goes into detail about how events in JavaFX work. No obligation, but if you think you’d get some value out of that, it’s here.

4. Disable a button without hiding it

Finally, sometimes you don’t really want to make a button disappear – you just want to set the button to be unusable by your user. That is, you want to lock it against further

A button can be disabled by invoking the setDisable() method on the button object, passing the boolean value true. This will prevent users interacting with the button, and will change the visual appearance of the button to signify it has been disabled.

button.setDisable(true);

The default styling for a disabled button is a flatter, greyed out appearance. That indicates to the user that it cannot be “depressed” (i.e. clicked). The button itself will not respond to user inputs by either the mouse of the keyboard.

Conclusions

Hiding a button in JavaFX is as simple as invoking setVisible(false) on the button object. This informs the background rendering toolkit not to render the image of the button to the Scene.

If you don’t specify anything else, JavaFX will layout nodes in the same layout pane as the button as if the button’s still there. You might want that effect, or you might not. You can instruct JavaFX to rearrange the remaining nodes into the space that’s freed up by the button’s disappearance: to achieve this, you’ll need to invoke setManaged(false), which removed is from layout calculations.

To create a smooth animation of the button fading from the scene, you can use the FadeTransition animation. By setting the to property of the animation to zero, we can fade the button completely.

Finally, to disable a button without removing it from the scene, you can invoke setDisable(true), which will partially fade and flatten the button, This indicates to the user that it can not be interacted with, while the button itself will no longer accept user inputs.