В вашем коде есть пара ошибок.Наиболее актуально то, что вы используете FXCollections.observableArrayList(Collection)
.Этот Javadoc этого метода гласит:
Создает новый список наблюдаемых массивов и добавляет к нему содержимое коллекции col.
Другими словами, копирует Collection
в новый ObservableList
, который поддерживается ArrayList
.Любые обновления к исходному Collection
никогда не будут даже добавлены к ObservableList
.Вы должны использовать FXCollections.observableList(List)
, если хотите, чтобы переданный List
был поддержкой List
.
Javadoc для FXCollections.observableList(List)
(выделение мое):
Создает ObservableList, который поддерживается указанным списком.Об операциях мутации в экземпляре ObservableList будет сообщено наблюдателям, которые зарегистрировались в этом экземпляре. Обратите внимание, что об операциях мутации, выполненных непосредственно в нижележащем списке, не сообщается наблюдателям ни одного ObservableList, который его обертывает.
Этот Javadoc намекает на вторую проблему.Если вы не делаете по-другому в коде, который вы не опубликовали, то, по-видимому, вы добавляете элементы в поле ArrayList
(с именем allParts)
. Из-за этого ObservableList
никогда не знает о каких-либо изменениях, и, таким образом, никакие события изменения не запускаются.Срабатывание событий изменения кодируется в ObservableList
. Если вы хотите получать уведомления об изменениях, вы должны получить доступ к списку только через ObservableList
, который охватывает ArrayList
.
В этом случае вашкод по-прежнему будет работать (когда вы звоните tableView.refresh()
), если бы не факт, что вы также оберните ObservableList
в FilteredList
. A FilteredList
создает «представление» поддержки ObservableList
. Еслиподдержка ObservableList
никогда не запускает никаких изменений, FilteredList
никогда не уведомляется о каких-либо изменениях, что означает, что он никогда не узнает об обновлении этого "представления". Это означает, что когда вы добавляете элементы в ArrayList
, эти новые элементы "находятся вне представления"(если бы вы заменили элемент, который находится" внутри вида ", изменение было бы видно).
Это поведение можно увидеть с помощью следующего кода:
import java.util.*;
import javafx.collections.*;
import javafx.collections.transformation.*;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
ObservableList<String> obsList = FXCollections.observableList(list);
FilteredList<String> filteredList = new FilteredList<>(obsList);
System.out.println("INITIAL STATE");
System.out.printf("\tList: %s%n", list);
System.out.printf("\tFilteredList: %s%n", filteredList);
list.add("Goodbye");
list.add("World");
System.out.println("AFTER ADDING ELEMENTS");
System.out.printf("\tList: %s%n", list);
System.out.printf("\tFilteredList: %s%n", filteredList);
list.set(0, "Foo");
list.set(1, "Bar");
System.out.println("AFTER REPLACING ELEMENTS");
System.out.printf("\tList: %s%n", list);
System.out.printf("\tFilteredList: %s%n", filteredList);
}
}
Какие отпечатки выt:
INITIAL STATE
List: [Hello, World]
FilteredList: [Hello, World]
AFTER ADDING ELEMENTS
List: [Hello, World, Goodbye, World]
FilteredList: [Hello, World]
AFTER REPLACING ELEMENTS
List: [Foo, Bar, Goodbye, World]
FilteredList: [Foo, Bar]
Учитывая все это, самый простой способ исправить ваш код - сделать allParts
ObservableList
.В противном случае вы должны позаботиться о том, чтобы использовать только ObservableList
, созданный вами вокруг ArrayList
.
Редактировать
Вы также упоминаете, что «ЕслиЯ оставляю поле поиска пустым и нажимаю кнопку поиска, появляется четвертая часть ".Я хочу обратиться к этому.Вот ваш код с пояснениями, почему новый Part
появляется в TableView
, когда вы нажимаете кнопку поиска:
/*
* I extracted the FXCollections.observableArrayList(Collection) out of the FilteredList
* constructor to more easily see what is going on.
*/
/*
* You create a **new** ObservableList using FXCollections.observableArrayList(Collection). This basically
* creates a *snapshot* of the List returnd by getAllParts() as it currently is. At this point the 4th
* Part is in that returned List. This means the newly created ObservableList will also contian the new
* Part (since observableArrayList(Collection) copies the data). However, the *old* ObservableList that
* was already set on the TableView *does not* contain that 4th Part.
*/
ObservableList<Part> parts = FXCollections.observableArrayList(inventory.getAllParts());
// You create a FilteredList that performs no filtering around "parts". Note
// here that a Predicate that always returns true is equivalent to passing null
// as the Predicate.
FilteredList<Part> filteredData = new FilteredList<>(parts, p -> true);
// Get the search criteria
String newValue = txtPartSearch.getText();
filteredData.setPredicate(part -> {
if (newValue == null || newValue.isEmpty()) {
return true; // don't filter if there is no search criteria
// since the newValue will be null or blank in this
// case no Parts are filtered
}
// filter based on lower-case names and search critiera
String lowerCaseFilter = newValue.toLowerCase();
if (part.getName().toLowerCase().contains(lowerCaseFilter)) {
return true;
}
// else filter by ID
return Integer.toString(part.getPartID()).equals(lowerCaseFilter);
});
// Wrap the FilteredList in a SortedList and bind the comparatorProperty to
// the comparatorProperty of the TableView (allows sorting by column).
SortedList<Part> sortedData = new SortedList<>(filteredData);
sortedData.comparatorProperty().bind(tblParts.comparatorProperty());
// Set the sortedData to the TableView
tblParts.setItems(sortedData);
Итак, основная причина, по которой при поиске вы видите новое Part
шоуЭто связано с тем, что вы создаете новый ObservableList
каждый раз при поиске.Этот новый ObservableList
имеет самое последнее состояние getAllParts()
List
.Кроме того, как я уже упоминал в комментариях, ваша правка в основном делает то же самое, что и ваш код сортировки.Поскольку вы делаете:
inventory.addPart(new Part(6,"Test",5.23,4,2,8));
tblParts.setItems(FXCollections.observableArrayList(inventory.getAllParts()));
, который добавляет Part
перед созданием ObservableList
.Опять же, FXCollections.observableArrayList(Collection)
делает снимок из Collection
, который при вызове метода содержит этот новый Part
.Если вы перевернете код на:
tblParts.setItems(FXCollections.observableArrayList(inventory.getAllParts()));
inventory.addPart(new Part(6, "Test", 5.23, 4, 2, 8));
, тогда свойство TableView
items
не будет содержать новое Part
.Однако allParts
ArrayList
в inventory
будет .