JavaFX is the new standard library used in Java to build graphics applications, but many programmers still stick to using Swing or even AWT. Here are some suggestions on how to build responsive, fast applications with new awesome features in the JavaFX tool set!
1. Attribute value
If you have a complete understanding of JavaFX components, mobile has encountered the property. Almost every value in the FX library can be observed, the width of the partition, the size of the image, the text in the label, the child items in a list, and the status of the checkbox. Attributes are divided into alternatives: writable attributes and readable attributes. Writable values can be modified, either using the setter method or directly. JavaFX handles the event handling process and ensures that every component that depends on this property is notified. Readable properties have methods that allow you to receive notifications when their values are modified.
Example:
// Readable-and writable StringProperty name = new SimpleStringProperty("Emil"); // Read-only ObservableBooleanValue nameIsEmpty = name.isEmpty();2. Bind value
When you have a writable and readable value, you can start defining rules about how these values are associated. A writable property can be bound to a readable property, so its value will always match the readable one. The bindings don't happen immediately, but they will be done before the value is observed (and look at what I did there). The binding can be one-way or two-way. Of course, if they are bidirectional, both properties need to be writable.
Example:
TextField fieldA = new TextField();TextField fieldB = new TextField();fieldA.prefWidthProperty().bind(fieldB.widthProperty());
3. Observable list
Attributes are not the only things that can be observed. If the list is encapsulated into an ObservableList, then the members of the list can also be observed. The response model of ObservableList is quite advanced. You can not only receive notifications when the list is modified, but also see how the list is modified.
Example:
List<String> otherList = Arrays.asList("foo", "bar", "bar");ObservableList<String> list = FXCollections.observableList(otherList);list.addListener((ListChangeListener.Change<? extends String> change) -> { System.out.println("Received event."); while (change.next()) { if (change.wasAdded()) { System.out.println( "Items " + change.getAddedSubList() + " was added."); } if (change.wasRemoved()) { System.out.println( "Items " + change.getRemoved() + " was removed."); } }});System.out.println("Old list: " + list); list.set(1, "foo");System.out.println("New list: " + list);The running output of the above code is as follows:
Old list: [foo, bar, bar]Received event.Items [foo] was added.Items [bar] was removed.New list: [foo, foo, bar]
As you can see, the setting operation will only trigger an event once.
4. StringConverter
Sometimes you will find that you don't need to extract the values from a component when you want to create a binding. A typical example of this is that you have a StringProperty with a path that you get from a TextField. If you want to have an observable property with this value represented as Path, you need to create a StringConverter for it.
Example:
TextField fileLocation = new TextField();StringProperty location = fileLocation.textProperty();Property<Path> path = new SimpleObjectProperty<>(); Bindings.bindBidirectional(location, path, new StringConverter<Path>() { @Override public String toString(Path path) { return path.toString(); } @Override public Path fromString(String string) { return Paths.get(string); }});Object properties are not two-way bindings to the values of the text field.
5. Expressions
Using the Bindings class above, you can create any type of expression. For example, you have two text fields that allow users to enter information. Now I want to define a read-only domain, which will always contain a string. If the lengths of the two strings are equal, the two strings will be mixed together character-by-character intervals for display. If the lengths are not equal, a help message is displayed.
Example:
TextField first = new TextField();TextField second = new TextField();TextField mix = new TextField(); mix.textProperty().bind( Bindings.when( first.lengthProperty().isEqualTo(second.lengthProperty()) ).then(Bindings.createStringBinding( () -> { int length = first.lengthProperty().get(); String firstText = first.textProperty().get(); String secondText = second.textProperty().get(); char[] result = new char[length * 2]; for (int i = 0; i < length; i++) { result[i * 2] = firstText.charAt(i); result[i * 2 + 1] = secondText.charAt(i); } return new String(result); }, first.textProperty(), second.textProperty() )).otherwise("Please enter two strings of exactly the same length."));This is just a little bit of the many features of JavaFX. Hopefully you can find more creative ways to leverage this event system!