EDIT --- Показаны классы объектов, добавлен код внутри метода инициализации, удален прежний метод фильтрации и удалено OnAction для TextField из FXML. ---
Мои первые попытки разобраться в этом привели к множеству проблем с Android, так что я здесь.
Я сделал простой графический интерфейс, используя JavaFX, Scenebuilder и FXML. Этот графический интерфейс имитирует инвентарь заводского цеха и может добавлять/удалять из/отображать/сохранять в файл из ObservableList
. Также предполагается фильтровать объекты на основе частичных String
, введенных пользователем в TextField
.
Это было просто в предыдущем воплощении этой программы, так как все это было через командную строку; однако я столкнулся с новой проблемой, с которой никогда раньше не сталкивался.
Каждый объект печатается с псевдослучайным идентификационным номером с заданным пользователем префиксом (F для цветов, W для сорняков, H для трав, Fn для грибов), именем, цветом и логическими атрибутами, такими как «колючий», «ароматный». , "съедобный" и т. д. Они определяются радиокнопками. Например, если пользователь вводит все значения нового цветка, он печатается как: «ID: F-21, имя: роза, цвет: красный, колючий? Ложь, душистый? Истина».
Вот мои исходные ObservableList и FilteredList:
ObservableList<Plant> observablePlantList = FXCollections.observableArrayList();
FilteredList<Plant> filteredList = new FilteredList<Plant>(observablePlantList);
Вот мой класс Plant и один подкласс (есть 4 абсолютно одинаковых), чтобы показать, как они отображаются в списке (логические значения — это переключатели):
public class Plant {
public String ID;
public String name;
public String color;
public boolean smell;
public boolean thorns;
public boolean edible;
public boolean poisonous;
public boolean flavor;
public boolean medicine;
public boolean seasonal;
public int idNum;
public Plant(String ID, int idNum, String name, String color, boolean smell, boolean thorns, boolean edible, boolean poisonous, boolean flavor, boolean medicine, boolean seasonal) {
this.ID = ID;
this.idNum = randomID(idNum);
this.name = name;
this.color = color;
this.smell = false;
this.thorns = false;
this.edible = false;
this.poisonous = false;
this.flavor = false;
this.medicine = false;
this.seasonal = false;
}
public void setColor(String color) {this.color = color;}
public void setID(String ID) {this.ID = ID;}
public void setName(String name) {this.name = name;}
public String getID() {return ID;}
public String getName() {return name;}
public int randomID(int idNum) {
Random randomNum = new Random();
idNum = randomNum.nextInt(50);
return idNum;
}
public String toString() {
return "ID: " + this.ID + "-" + this.idNum + ", Name: " + this.name + ", Color: " + this.color;
}
}
Подкласс
public class Flower extends Plant {
public Flower(String ID, int idNum, String name, String color, boolean smell, boolean thorns, boolean edible, boolean poisonous, boolean flavor, boolean medicine, boolean seasonal) {
super(ID, idNum, name, color, smell, thorns, edible, poisonous, flavor, medicine, seasonal);
}
public void setSmell(boolean smell) {
this.smell = smell;
}
public void setThorns(boolean thorns) {
this.thorns = thorns;
}
public String toString() {
return super.toString() + ", Scent? " + this.smell + ", Thorns? " + this.thorns;
}
}
Это то, что у меня есть в моем методе инициализации благодаря предложению в ответе ниже. Проблема в том, что ничего не меняется:
@Override
public void initialize(URL fxmlFileLocation, ResourceBundle rb) {
plantList.setItems(filteredList);
//binding filterInput text entries
filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> {
String filterText = filterInput.getText();
if(filterText == null || filterText.isEmpty()) {
return null;
}
else {
final String uppercase = filterText.toUpperCase();
return (plant) -> plant.getName().toUpperCase().contains(uppercase);
}
}, filterInput.textProperty()));
Моя цель — фильтровать ObservableArrayList в режиме реального времени, а не использовать кнопку, которая фильтрует и показывает элементы в новой сцене. Я видел, как это реализовано, и мне очень нравится функциональность.
Спасибо за любую предложенную помощь.
FilteredList
, так как он неизменяем. ЦельюFilteredList
является предоставление представления другого списка, ограниченного теми элементами, которые соответствуютPredicate
. Кстати: проверка внутриPredicate
, является ли новая строка пустой илиnull
, и преобразование этой строки в верхний регистр неоптимально, поскольку это нужно делать только один раз для каждого изменения текста, а не один раз для вызоваPredicate.test
. То, что вы пытаетесь сделать, почти то же самое, что и я в своем ответе; Разница в том, что я использую привязку для замены предиката, а вы делаете это из слушателя. - person fabian   schedule 25.11.2015bind
регистрирует прослушиватель,Bindings.createObjectBinding
тоже регистрирует прослушиватель, аFilteredList
прослушивает изменения в исходном списке.Predicate
— это просто функциональный интерфейс, предоставляющий метод, который получает один аргумент и возвращаетboolean
. Он часто используется для принятия решения на основе входных данных. То, что делаетFilteredList
, очень похоже на то, чтоfilter
делает сStream
, если вы более знакомы с этим. - person fabian   schedule 26.11.2015