This video demonstrates the MenuItem behavior. Initially, the Save Profile MenuItem is disabled. Typing into a TextField enables it. Performing the Save operation disables the MenuItem again.
@FXML MenuItem miSave;
I have a flag in the application called needsSave which is very clear in its purpose. It is also a field.
private final BooleanProperty needsSave = new SimpleBooleanProperty(false);
JavaFX binding let's me link the disabledProperty of miSave to the needsSave property. For readbility, I'm actually binding to the needsSave.not() property. I feel this is more readable than defining my flag as "doesNotNeedSave", especially later on when I call "needsSave(true)". This code appears in the @FXML initialize() method.
This binding means that when the needsSave.not property changes to true, disable on the MenuItem will also be true. In English, if the document doesn't need to be saved, no save MenuItem will be available.
When the user types into the TextFields, and InvalidationListener fires that sets needsSave to true. This will make the disabledProperty false (needsSave.not = false). In the class definition,
private final InvalidationListener needsSaveListener = (evt) -> needsSave.set(true);
In the @FXML initialize(),
tfSourceFile.textProperty().addListener(new WeakInvalidationListener(needsSaveListener)); tfTargetFile.textProperty().addListener(new WeakInvalidationListener(needsSaveListener));
There is a needsSave.set(false) call made after the save operation takes place.
While you can skip binding and directly call miSave.setDisabled(), binding is more readable and scalable. Binding's improved readability comes from linking the presentation (disabledProperty) to the intent (needsSave.not). The scalability comes from being able to bind other non-MenuItem disabled properties like an alternate Button to the needsSave property.
The code in this post is hosted at GitHub. See the class "ResignatorMainViewController".