В this question Мне было показано, как решить проблему смены свойства, изменив его обертывающий объект и, таким образом, не отправляя обновления, которые он изменил. Раствор использует ReactFX:Как выполнить пользовательскую привязку с Varation ReactFX?
class Cell {
private final ObjectProperty<Shape> shape = new SimpleObjectProperty<>(new Shape());
// all getters and setterts
public static class Shape {
private final IntegerProperty size = new SimpleIntegerProperty(0);
// all getters and setterts
}
public static void main(String[] args) {
Var<Number> sizeVar = Val.selectVar(cell.shapeProperty(), Shape::sizeProperty);
sizeVar.addListener(
(obs, oldSize, newSize) -> System.out.println("Size changed from "+oldSize+" to "+newSize));
}
Так что теперь, если сам shape
свойство изменяет это вызывает изменение в size
тоже (если новая форма не имеет такой же размер). Но теперь я хочу привязать свойство к пользовательским привязкам, и у меня возникла проблема, описанная ниже.
Мои классы данных являются следующие:
class Cell {
private final ObjectProperty<Shape> shape = new SimpleObjectProperty<>();
public final ObjectProperty<Shape> shapeProperty() { return shape; }
public final Shape getShape() { return shapeProperty().get(); }
public final void setShape(Shape shape) { shapeProperty().set(shape); }
// other properties
}
class Shape {
private final IntegerProperty size = new SimpleIntegerProperty();
public final IntegerProperty sizeProperty() { return size; }
public final int getSize() { return size.get(); }
public final void setSize(int size) { sizeProperty().set(size); }
// other properties
}
И я хочу, чтобы создать представление GUI для них путем связывания их свойства к свойствам графического интерфейса. Я делаю это так:
class CellRepresentation extends Group {
private final Cell cell;
CellRepresentation(Cell cell) {
this.cell = cell;
getChildren().add(new ShapeRepresentation() /*, other representations of things in the cell*/);
}
private class ShapeRepresentation extends Cylinder {
ObjectProperty<Shape> shape;
private ShapeRepresentation() {
super(100, 100);
shape = new SimpleObjectProperty<Shape>(cell.getShape());
shape.bind(cell.shapeProperty());
Var<Number> sizeVar = Val.selectVar(cell.shapeProperty(), Shape::sizeProperty);
// THIS WILL WORK
materialProperty().bind(Bindings.createObjectBinding(() -> {
if (shape.get() == null)
return new PhongMaterial(Color.TRANSPARENT);
return new PhongMaterial(Color.RED);
}, sizeVar));
// THIS WILL NOT WORK
materialProperty().bind(sizeVar.map(n -> {
if (shape.get() == null)
return new PhongMaterial(Color.TRANSPARENT);
return new PhongMaterial(Color.RED);
}));
}
}
// the other representations of things in the cell
}
Когда я запускаю код ниже, первый вариант привязки создаст прозрачный цилиндр. Второй вариант создаст белый (по умолчанию цветной) цилиндр. Я не знаю, почему это происходит.
public class Example extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
Cell cell = new Cell();
CellRepresentation cellRep = new CellRepresentation(cell);
Group group = new Group(cellRep);
Scene scene = new Scene(group, 200, 200, Color.AQUA);
stage.setScene(scene);
stage.show();
}
}
Я также открыт для разработки предложений, если это не является хорошим способом для создания представления для классов данных с использованием привязок.
Что такое 'size' в последнем блоке кода ? Вам не нужно что-то вроде 'if (sizeVar.getValue(). IntValue() == 1) {...}' и т. Д.? –
@James_D 'size' является свойством' Shape'. Я пробовал раньше с строкой, которую вы написали (принимая значение от 'sizeVar'), но не было никакой разницы. Я создам MCVE. я думал, что это просто неправильное использование. – Mark
Да, я в замешательстве. Разумеется, 'size' является членом' Shape', но привязка находится вне класса 'Shape'. И это все равно не будет компилироваться, потому что 'size' является' IntegerProperty' и не может сравниться с '1'' == '. Если эта версия не работает, привязка, вероятно, собирает мусор. Мой ответ не работает? –