#javafx #javafx-8
#javafx #javafx-8
Вопрос:
Я использую formsfx и освоился с этим, однако я не знаю, как использовать .addEvent обработчик для поля.
EventHandler<KeyEvent> handler = new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
System.out.println("Handling event " event.getEventType());
}
};
Field.ofDoubleType(model.priceProperty())
.label("price")
.required("cant be empty")
.addEventHandler(handler).
затем я получаю сообщение
addEventHandler
(javafx.event.EventType<com.dlsc.formsfx.model.event.FieldEvent>,
EventHandler<? super FieldEvent>)
in Field cannot be applied
to
(javafx.event.EventHandler<javafx.scene.input.KeyEvent>)
после того, как я попытался использовать то же поле event, но безуспешно, я что-то упускаю, я просто не знаю, что.
В описании говорится, что он принимает тип FieldEvent и обработчик событий.
Комментарии:
1. Когда вы говорите: » после того, как я попытался использовать то же поле event, но безуспешно «, что именно пошло не так? Еще одна ошибка компиляции? Код не сделал то, что вы хотели? Что должен делать этот обработчик событий?
Ответ №1:
Field.ofDoubleType возвращает поле, которое является оболочкой для отображаемого содержимого. Фактическим узлом, который отображается в SceneGraph, является field.getRenderer(). К сожалению, это не тот фактический элемент управления, с которым вы хотите иметь дело. Это снова оболочка (GridPane) всего необходимого для вашего элемента управления формой (textfield, choicebox, checkbox и т.д.).
getRenderer() возвращает SimpleControl, а стандартного API для возврата точного элемента управления формой не существует. Например, SimpleTextControl содержит TextField, TextArea amp; Label в качестве своих дочерних элементов, и соответствующий узел отображается в scenegraph на основе контекста.
По этой причине очень сложно установить обработчик на точный узел. (из-за отсутствия API)
Таким образом, единственный узел, к которому у вас есть доступ, — это средство визуализации (панель сетки). Вы можете попробовать установить обработчики для этой панели сетки. Но в большинстве случаев это не сработает, потому что большинство элементов управления по умолчанию используют события в обработчиках.
Один из способов исправить вашу проблему заключается в том, что вместо обработчика вы можете полагаться на фильтры. Установка фильтра на панели сетки позволит вам узнать, нужно ли прослушивать соответствующие события.
Итак, вы можете попробовать приведенный ниже код:
EventHandler<KeyEvent> handler = new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
System.out.println("Handling event " event.getEventType());
}
};
Field priceField = Field.ofDoubleType(model.priceProperty())
.label("price")
.required("cant be empty");
priceField.getRenderer().addEventFilter(KeyEvent.KEY_PRESSED, handler);
ОБНОВЛЕНИЕ : демо-модель.java демонстрационного кода formsfx.
package com.dlsc.formsfx.demo.model;
import com.dlsc.formsfx.model.structure.Field;
import com.dlsc.formsfx.model.structure.Form;
import com.dlsc.formsfx.model.structure.Group;
import com.dlsc.formsfx.model.structure.Section;
import com.dlsc.formsfx.model.util.ResourceBundleService;
import com.dlsc.formsfx.model.validators.DoubleRangeValidator;
import com.dlsc.formsfx.model.validators.IntegerRangeValidator;
import com.dlsc.formsfx.model.validators.RegexValidator;
import com.dlsc.formsfx.model.validators.StringLengthValidator;
import com.dlsc.formsfx.view.controls.SimpleCheckBoxControl;
import com.dlsc.formsfx.view.controls.SimpleRadioButtonControl;
import com.dlsc.formsfx.view.util.ColSpan;
import javafx.event.EventHandler;
import javafx.scene.input.KeyEvent;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* This class is used to create the form and holds all the necessary data. This
* class acts as a singleton where the current instance is available using
* {@code getInstance}.
*
* @author Sacha Schmid
* @author Rinesch Murugathas
*/
public final class DemoModel {
private Country country = new Country();
/**
* These are the resource bundles for german and english.
*/
private ResourceBundle rbDE = ResourceBundle.getBundle("demo-locale", new Locale("de", "CH"));
private ResourceBundle rbEN = ResourceBundle.getBundle("demo-locale", new Locale("en", "UK"));
/**
* The default locale is English, thus the {@code ResourceBundleService} is
* initialised with it.
*/
private ResourceBundleService rbs = new ResourceBundleService(rbEN);
private Form formInstance;
/**
* Creates or simply returns to form singleton instance.
*
* @return Returns the form instance.
*/
public Form getFormInstance() {
if (formInstance == null) {
createForm();
}
return formInstance;
}
/**
* Creates a new form instance with the required information.
*/
private void createForm() {
EventHandler<KeyEvent> handler = event -> System.out.println("Handling event " event.getEventType());
Field field = Field.ofStringType(country.nameProperty())
.label("country_label")
.placeholder("country_placeholder")
.required("required_error_message")
.validate(StringLengthValidator.atLeast(2, "country_error_message"));
field.getRenderer().addEventFilter(KeyEvent.KEY_PRESSED,handler);
formInstance = Form.of(
Group.of(
field,
Field.ofStringType(country.isoProperty())
.label("ISO_3166_label")
.placeholder("ISO_3166_placeholder")
.required("required_error_message")
.validate(StringLengthValidator.exactly(2, "ISO_3166_error_message")),
Field.ofBooleanType(country.independenceProperty())
.label("independent_label")
.required("required_error_message"),
Field.ofDate(country.getIndependenceDay())
.label("independent_since_label")
.required("required_error_message")
.placeholder("independent_since_placeholder")
),
Section.of(
Field.ofStringType(country.currencyShortProperty())
.label("currency_label")
.placeholder("currency_placeholder")
.validate(StringLengthValidator.exactly(3, "currency_error_message"))
.span(ColSpan.HALF),
Field.ofStringType(country.currencyLongProperty())
.label("currency_long_label")
.placeholder("currency_long_placeholder")
.span(ColSpan.HALF),
Field.ofDoubleType(country.areaProperty())
.label("area_label")
.format("format_error_message")
.placeholder("area_placeholder")
.validate(DoubleRangeValidator.atLeast(1, "area_error_message"))
.span(ColSpan.HALF),
Field.ofStringType(country.tldProperty())
.label("internet_TLD_label")
.placeholder("internet_TLD_placeholder")
.span(ColSpan.HALF)
.validate(
StringLengthValidator.exactly(3, "internet_TLD_error_message"),
RegexValidator.forPattern("^.[a-z]{2}$", "internet_TLD_format_error_message")
),
Field.ofStringType(country.dateFormatProperty())
.label("date_format_label")
.placeholder("date_format_placeholder")
.multiline(true)
.span(ColSpan.HALF)
.validate(StringLengthValidator.atLeast(8, "date_format_error_message")),
Field.ofSingleSelectionType(country.allSidesProperty(), country.driverSideProperty())
.required("required_error_message")
.label("driving_label")
.span(ColSpan.HALF)
.render(new SimpleRadioButtonControl<>()),
Field.ofStringType(country.timeZoneProperty())
.label("time_zone_label")
.placeholder("time_zone_placeholder")
.span(ColSpan.HALF)
.validate(StringLengthValidator.exactly(3, "time_zone_error_message")),
Field.ofStringType(country.summerTimeZoneProperty())
.label("summer_time_zone_label")
.placeholder("summer_time_zone_placeholder")
.span(ColSpan.HALF)
.validate(StringLengthValidator.atLeast(3, "summer_time_zone_error_message"))
).title("other_information_label"),
Section.of(
Field.ofSingleSelectionType(country.allCapitalsProperty(), country.capitalProperty())
.label("capital_label")
.required("required_error_message")
.tooltip("capital_tooltip")
.span(ColSpan.HALF),
Field.ofIntegerType(country.populationProperty())
.label("population_label")
.format("format_error_message")
.placeholder("population_placeholder")
.required("required_error_message")
.span(ColSpan.HALF)
.validate(IntegerRangeValidator.atLeast(1, "population_error_message")),
Field.ofMultiSelectionType(country.allContinentsProperty(), country.continentsProperty())
.label("continent_label")
.required("required_error_message")
.span(ColSpan.HALF)
.render(new SimpleCheckBoxControl<>()),
Field.ofMultiSelectionType(country.allCitiesProperty(), country.germanCitiesProperty())
.label("german_cities_label")
.span(ColSpan.HALF),
Field.ofPasswordType("secret")
.label("secret_label")
.required("required_error_message")
.span(ColSpan.HALF)
.validate(StringLengthValidator.between(1, 10, "secret_error_message"))
).title("cities_and_population_label")
).title("form_label")
.i18n(rbs);
}
/**
* Sets the locale of the form.
*
* @param language The language identifier for the new locale. Either DE or EN.
*/
public void translate(String language) {
switch (language) {
case "EN":
rbs.changeLocale(rbEN);
break;
case "DE":
rbs.changeLocale(rbDE);
break;
default:
throw new IllegalArgumentException("Not a valid locale");
}
}
public Country getCountry() {
return country;
}
}
Комментарии:
1. Спасибо, это интересно, однако заметили ли вы, что каждый раз событие get запускается 2 раза? Я использовал ваш код и сгенерировал форму, поместил форму в средство визуализации, но каждый раз, когда я нажимаю кнопку, я получаю обработку события KEY_PRESSED Обработка события KEY_PRESSED, и источник также тот же, его панель сетки
2. Вы проверили, создаете ли вы несколько полей или устанавливаете несколько обработчиков. Потому что я проверил демонстрационный код (исходный код formsfx demo), и он запускается только один раз. Я только что обновил DemoModel.java демонстрационный код formsfx для вашей справки.
3. вы правы, я действительно допустил ошибку в своем коде, все работает так, как вы сказали! Большое вам спасибо за подробный ответ и объяснение.
Ответ №2:
Попробуйте использовать:
model.priceProperty().addListener(event -> {
//your code here
});