Обзор
Как разработчик Swing в течение десяти лет, я был в восторге от особенностей, представленных с JavaFX 2.0, особенно с богатыми, плавными, высокоуровневыми средствами привязки данных. Этот объект сам по себе стоит затрат на изучение нового API (что намного меньше, так как отказ от FX script). Это будет иметь прямое отношение к читабельности и поддержке моего кода синхронизации модели/представления.
До сих пор я обладаю большим успехом на уровне первого и базовых производных привязок, но изо всех сил пытаюсь выяснить способ "JavaFX" привязки одного значения к значению двух или более уровней косвенности в графике данных.
Проблема
Как показано в приведенном ниже примере кода, я пытаюсь использовать javafx.beans.binding.Bindings.select()
для синхронизации текстового значения метки с одним из содержащиеся свойства выбранного в данный момент элемента в ComboBox. Этот код является простым примером чего-то более сложного, который я пытаюсь сделать, поэтому я понимаю, что это не сложно сделать с помощью API привязок более низкого уровня. Я хотел бы знать, возможно ли это с использованием API-интерфейса более высокого уровня, и если метод select(...)
фактически отслеживает изменения косвенных свойств (т.е. Свойство update, если либо свойство прямой, либо выбранное изменение подвыражения).
Документация и примеры на select(...)
являются разреженными, поэтому я надеюсь, что кто-то с передовым опытом с этим может сказать мне, пытаюсь ли я использовать API так, как он был разработан, или если есть другой способ использования высокопроизводительных приложений, для того, чтобы делать то, что я хочу.
Пример кода
Вот демо-код. При запуске есть ComboBox с двумя элементами в нем, а затем две метки. На первой метке отображается версия toString()
выбранного элемента. Вторая метка пытается отобразить одно из свойств выбранного элемента, но отображает только null
.
import static javafx.beans.binding.Bindings.*;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/** Testing cascading binding change triggers. */
public class SandboxTest extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
VBox root = new VBox(8);
root.setStyle("-fx-padding: 8;");
Scene s = new Scene(root);
stage.setWidth(200);
stage.setScene(s);
ComboBox<MoPoJo> list = new ComboBox<SandboxTest.MoPoJo>();
list.itemsProperty().set(FXCollections.observableArrayList(new MoPoJo("foo", "bar"), new MoPoJo("baz", "bat")));
Label direct = new Label();
direct.setTooltip(new Tooltip("Selected item to string"));
Label withSelect = new Label();
withSelect.setTooltip(new Tooltip("Second property of selected item"));
direct.textProperty().bind(convert(list.getSelectionModel().selectedItemProperty()));
withSelect.textProperty().bind(convert(select(list.getSelectionModel().selectedItemProperty(), "two")));
root.getChildren().addAll(list, direct, withSelect);
stage.show();
}
private static class MoPoJo {
private StringProperty _one = new SimpleStringProperty();
private StringProperty _two = new SimpleStringProperty();
private StringProperty _name = new SimpleStringProperty();
public MoPoJo(String o, String t) {
_one.set(o);
_two.set(t);
_name.bind(format("{ %s, %s }", oneProperty(), twoProperty()));
}
public StringProperty oneProperty() {
return _one;
}
public StringProperty twoProperty() {
return _two;
}
public ReadOnlyStringProperty nameProperty() {
return _name;
}
@Override
public String toString() {
return nameProperty().get();
}
}
}