I’ve taken a short break from the JavaFX and JPA series of articles because I wanted to start a new project that demonstrates common day to day tasks in JavaFX. I’ve called this project SampleFX5 and you can download it here.
At the moment there is only a single example which shows three different ways to show and hide part of a scene. While not the most complex of tasks as the example shows it can be made very easy (just two lines of code) or as complex as you want.
The code for the show / hide example is shown below:
package co.uk.wobblycogs.samplefx5; import java.net.URL; import java.util.ResourceBundle; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.TitledPane; import javafx.scene.control.ToggleButton; import javafx.scene.layout.VBox; public class ShowHideController implements Initializable { public static final String FRIENDLY_NAME = "Show / Hide"; public static final String NAME = "uk.co.wobblycogs.samplefx5.ShowHide"; public static final String FXML_RESOURCE = "/resources/fxml/ShowHide.fxml"; @FXML private TitledPane pane2; @FXML private ToggleButton pane2Toggle; @FXML private TitledPane pane3; @FXML private ToggleButton pane3Toggle; @FXML private TitledPane pane4; @FXML private ToggleButton pane4Toggle; @FXML private VBox togglePaneParent; private int pane3Position; public ShowHideController() { } @Override public void initialize(URL url, ResourceBundle rb) { pane2.managedProperty().bind(pane2.visibleProperty()); pane2.visibleProperty().bind(pane2Toggle.selectedProperty()); pane3Toggle.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) { if (newValue) { togglePaneParent.getChildren().add(pane3Position, pane3); } else { pane3Position = togglePaneParent.getChildren().indexOf(pane3); togglePaneParent.getChildren().remove(pane3); } } }); pane4Toggle.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) { if (newValue) { pane4.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); } else { pane4.setMaxSize(0, 0); pane4.setMinSize(0, 0); } } }); } }
Bind the Managed Property
As can be seen hiding pane two couldn’t be simpler. The managed property of the titled pane is bound to the visible property of the pane which is is in turn bound to the selected property of the toggle button. This really shows the power of the JavaFX binding framework and, if you can, this is the way to hide parts of the scene. The reason tis works is discussed in the javadoc for Node but essentially an unmanaged node effectively has zero width and height when the parent node calculates its preferred size and layout bounds.
Remove the Child from its Parent
The second example hides pane three. This method is acceptable but it means keeping track of the location of the pane in the parents child list. There are situations where this would’t be a problem such as when the hidden node is the last one in the list but generally you’ll need to keep track of where it was removed from so that you can put it back in the correct place. While not much of a hardship it’s not as clean as the first example.
Fiddle with the Size
I think this is a terrible method for hiding a node in the scene but I’ve included it for completeness. The problem is that it potentially requires you to keep track of numerous different variables. In this example I’m letting the layout engine get on with it but if you had a layout that relied on carefully sized nodes you’d probably need to remember min, pref and max width and height. The only real benefit is that because the node isn’t removed from it’s parent there’s no problems re-inserting it into the scene.