#properties #bind #javafx-8
#свойства #привязка #javafx-8
Вопрос:
На мой взгляд, у меня есть HBox
@FXML
private HBox hboxWarning;
и я хочу скрыть / показать его в соответствии со значением
private ObjectProperty<Integer> maxClientCount;
Если maxClientCount > 10
then hboxWarning
виден, то он скрывается.
Я связал два элемента таким образом
hboxWarning.visibleProperty().bind(IntegerProperty.integerProperty(maxClientCount).greaterThan(10));
и работает хорошо. Моя проблема в том, что
IntegerProperty.integerProperty(maxClientCount)
обнуляет текущее значение maxClientCount
. Это ошибка JavaFX или я использую IntegerProperty.integerProperty
неправильно? И
как я могу достичь своей цели?
Комментарии:
1. это ошибка: javafx-jira.kenai.com/browse/RT-37523
Ответ №1:
Оказалось, что это не так просто, как предполагалось: основное исправление нуждается в дополнительных методах в двунаправленной привязке, чтобы справиться с измененной последовательностью типов чисел. Фактические привязки номеров являются частными, поэтому нет возможности получить доступ к коду обходного пути.
// method in u5, binds the wrong way round
// (for usage in IntegerProperty.integerProperty)
public static BidirectionalBinding bindNumber(Property<Integer> property1,
IntegerProperty property2)
// calls
private static <T extends Number> BidirectionalBinding bindNumber(Property<T> property1,
Property<Number> property2) {
Последовательность имеет решающее значение, потому что нам нужно приведение типа от Number к T при установке значения p1 (что безопасно, потому что мы знаем, что свойство number-type справляется с преобразованием из Number -> concrete type). Основное исправление просто добавляет все эти методы с переключаемой последовательностью параметров.
Для пользовательского взлома до выпуска JDK 8u20 единственный способ, который я вижу, — это использовать не специальные методы привязки номеров, а привязку к общему объекту:
public static IntegerProperty integerProperty(final Property<Integer> property) {
if (property == null) {
throw new NullPointerException("Property cannot be null");
}
return new IntegerPropertyBase() {
{
bindBidirectional(cast(property));
// original:
//BidirectionalBinding.bindNumber(property, this);
}
@Override
public Object getBean() {
return null; // Virtual property, no bean
}
@Override
public String getName() {
return property.getName();
}
@Override
protected void finalize() throws Throwable {
try {
unbindBidirectional(cast(property));
// original
// BidirectionalBinding.unbindNumber(property, this);
} finally {
super.finalize();
}
}
};
}
/**
* Type cast to allow bidi binding with a concrete XXProperty (with
* XX = Integer, Double ...). This is (?) safe because the XXProperty
* internally copes with type conversions from Number to the concrete
* type on setting its own value and exports the concrete type as
* needed by the object property.
*
*/
private static <T extends Number> Property<Number> cast(Property<T> p) {
return (Property<Number>) p;
}
Отнеситесь к этому с недоверием — при элементарном тестировании могут быть побочные эффекты, которые я пропустил.
Комментарии:
1. Спасибо @kleopatra. Я не очень хорошо понимаю, почему непроверенное приведение можно считать безопасным 🙂
2. нас интересует только значение, которое синхронизируется в привязке, выполняемой через setValue / GetValue . Тогда T должен быть типом конкретного числового типа, то есть IntegerProperty <-> ObjectProperty<Integer> или DoubleProperty <-> ObjectProperty<Double>, чтобы быть безопасным для другого
3. Ваш обходной путь работает!! Почему компилятор выдает мне «непроверенное» предупреждение в методе приведения? Число является суперклассом T… :/
Ответ №2:
Как правильно сказал @kleopatra, это ошибка JavaFX, исправленная в JDK 8u20.
Тем временем я использовал следующий обходной путь:
int maxClients = maxClientCount.get();
hboxWarning.visibleProperty().bind(IntegerProperty.integerProperty(maxClientCount).greaterThan(10));
maxClientCount.setValue(maxClients);
Я надеюсь, что это может кому-то помочь.
Комментарии:
1. я бы предпочел вообще не использовать фабрику — c amp; p, исправьте адаптер и используйте его до тех пор, пока не будет выпущено исправление. Разрешение установить поврежденное свойство, а затем отменить его, может вызвать проблемы с а) потенциальными слушателями (они получат неожиданные уведомления) б) самим адаптированным свойством (набор адаптера может нарушать внутренние правила проверки) Впрочем, как и во всех обходных путях ошибок, это дело вкуса 🙂
2. Я согласен с вами, что мой обходной путь может создать проблемы. Я бы последовал вашему совету, но я не понимаю, что я должен скопировать и вставить, а затем изменить? Класс IntegerProperty?
3. IntegerProperty.IntegerProperty — это статический метод, который внутренне обертывает свойство IntegerProperty вокруг вашего свойства<Integer> — c amp; p этот метод и инвертирует все привязки (свойство, this) к bind(this, property)
4. ах .. теперь я понимаю, почему ошибка произошла в первую очередь (только обнаружив ее, я никогда не пытался исправить ее сам) — общий ввод текста стоит на пути. Посмотрит на исправление в b20, а затем вернется