Tôi muốn hiển thị danh sách những người (được mã hóa trong POJOS và có chứa tên và họ) bằng cách sử dụng điều khiển ListView của JavaFX. Tôi đã tạo ListView và thêm danh sách những người như là một ObservableList. Mọi thứ hoạt động tốt nếu tôi xóa hoặc thêm một người mới vào ObservableList, nhưng những thay đổi trong POJO không kích hoạt cập nhật của ListView. Tôi phải xóa và thêm POJO đã sửa đổi từ ObservableList để kích hoạt cập nhật của ListView. Có khả năng hiển thị các thay đổi trong POJOS mà không có giải pháp được mô tả ở trên không?JavaFX: Cập nhật ListView nếu một phần tử của ObservableList thay đổi
Trả lời
ObservableList<String> items = FXCollections.observableArrayList();
ListView lv;
lv.setItems(items);
items.add();
items.remove;
thử này
list.remove(POJO);
list.add(index,POJO);
không có gì mới, phải không? Ngay cả OP đã đề cập đến điều này như một cách giải quyết ... – kleopatra
Có một số khía cạnh cho câu hỏi của bạn (và tôi không hoàn toàn là vấn đề :-) Tôi sẽ giả định rằng POJO của bạn bằng cách nào đó thông báo cho người nghe về những thay đổi, có thể là một JavaBean chính thức, tuân thủ hợp đồng thông báo của nó thông qua việc kích hoạt các sự kiện propertyChange khi cần hoặc một số phương tiện khác - nếu không, bạn sẽ cần một số thay đổi thủ công của thay đổi.
Cách tiếp cận cơ bản để tạo FX-ObservableList thông báo cho người nghe của riêng mình về đột biến của các phần tử được chứa là cấu hình nó với một cuộc gọi lại tùy chỉnh cung cấp một mảng các Observables. Nếu các yếu tố có fx-thuộc tính bạn sẽ làm điều gì đó như:
Callback<Person, Observable[]> extractor = new Callback<Person, Observable[]>() {
@Override
public Observable[] call(Person p) {
return new Observable[] {p.lastNameProperty(), p.firstNameProperty()};
}
};
ObservableList<Person> teamMembers = FXCollections.observableArrayList(extractor);
// fill list
Nếu POJO là-một JavaBean lõi full-fledged, tính chất của nó phải được thích nghi với fx-tài sản, f.i. bằng cách sử dụng JavaBeanProperty:
Callback<PersonBean, Observable[]> extractor = new Callback<PersonBean, Observable[]>() {
List<Property> properties = new ArrayList<Property>();
@Override
public Observable[] call(PersonBean arg0) {
JavaBeanObjectProperty lastName = null;
JavaBeanObjectProperty age = null;
try {
lastName = JavaBeanObjectPropertyBuilder.create()
.bean(arg0).name("lastName").build();
age = JavaBeanObjectPropertyBuilder.create()
.bean(arg0).name("age").build();
// hack around loosing weak references ...
properties.add(age);
properties.add(lastName);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return new Observable[] {lastName, age};
}
};
ObservableList<Person> teamMembers = FXCollections.observableArrayList(extractor);
// fill list
Lưu ý một caveat: không giữ một tham chiếu mạnh để các thuộc tính thích nghi nơi nào đó, họ sẽ nhanh chóng thu gom rác - và sau đó dường như không có hiệu lực ở tất cả (rơi vào bẫy một lần nữa và một lần nữa, không chắc chắn làm thế nào nếu có một chiến lược tốt để tránh nó).
Đối với bất kỳ phương tiện thông báo nào khác (có thể là hạt thô), bạn có thể triển khai bộ điều hợp tùy chỉnh: bộ điều hợp bên dưới nghe tất cả các thuộc tính của bean, nghe các loại sự kiện khác tương tự.
/**
* Adapt a Pojo to an Observable.
* Note: extending ObservableValue is too much, but there is no ObservableBase ...
*
* @author Jeanette Winzenburg, Berlin
*/
public class PojoAdapter<T> extends ObservableValueBase<T> {
private T bean;
private PropertyChangeListener pojoListener;
public PojoAdapter(T pojo) {
this.bean = pojo;
installPojoListener(pojo);
}
/**
* Reflectively install a propertyChangeListener for the pojo, if available.
* Silently does nothing if it cant.
* @param item
*/
private void installPojoListener(T item) {
try {
Method method = item.getClass().getMethod("addPropertyChangeListener",
PropertyChangeListener.class);
method.invoke(item, getPojoListener());
} catch (NoSuchMethodException | SecurityException | IllegalAccessException |
IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* Returns the propertyChangeListener to install on each item.
* Implemented to call notifyList.
*
* @return
*/
private PropertyChangeListener getPojoListener() {
if (pojoListener == null) {
pojoListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
fireValueChangedEvent();
}
};
}
return pojoListener;
}
@Override
public T getValue() {
return bean;
}
}
Đó là việc sử dụng chỉ là tương tự như trên (nhận được nhàm chán, không phải là nó :-)
Callback<PersonBean, Observable[]> extractor = new Callback<PersonBean, Observable[]>() {
@Override
public Observable[] call(PersonBean arg0) {
return new Observable[] {new PojoAdapter<PersonBean>(arg0)};
}
};
ObservableList<Person> teamMembers = FXCollections.observableArrayList(extractor);
// fill list
Thật không may, cập nhật tự động của một ListView với danh sách mát mẻ như vậy sẽ không làm việc đáng tin cậy do a bug that's fixed only in jdk8. Trong các phiên bản trước đó, bạn đang trở lại tại quảng trường 1 - bằng cách nào đó lắng nghe với sự thay đổi và sau đó tự cập nhật danh sách:
protected void notifyList(Object changedItem) {
int index = list.indexOf(changedItem);
if (index >= 0) {
// hack around RT-28397
//https://javafx-jira.kenai.com/browse/RT-28397
list.set(index, null);
// good enough since jdk7u40 and jdk8
list.set(index, changedItem);
}
}
Cảm ơn bạn rất nhiều vì đã báo trước, bạn đã đọc về nó ở đâu? Bạn vui lòng chia sẻ nó ở đây :) – TuanAnh207
Bạn có thể kích hoạt một ListView.EditEvent
— mà sẽ gây ra ListView
để cập nhật — bằng cách gọi phương pháp ListView::fireEvent
được kế thừa từ javafx.scene.Node
. Ví dụ,
/**
* Informs the ListView that one of its items has been modified.
*
* @param listView The ListView to trigger.
* @param newValue The new value of the list item that changed.
* @param i The index of the list item that changed.
*/
public static <T> void triggerUpdate(ListView<T> listView, T newValue, int i) {
EventType<? extends ListView.EditEvent<T>> type = ListView.editCommitEvent();
Event event = new ListView.EditEvent<>(listView, type, newValue, i);
listView.fireEvent(event);
}
Hoặc như một liner,
listView.fireEvent(new ListView.EditEvent<>(listView, ListView.editCommitEvent(), newValue, i));
Đây là một ứng dụng mẫu để chứng minh việc sử dụng nó.
/**
* An example of triggering a JavaFX ListView when an item is modified.
*
* Displays a list of strings. It iterates through the strings adding
* exclamation marks with 2 second pauses in between. Each modification is
* accompanied by firing an event to indicate to the ListView that the value
* has been modified.
*
* @author Mark Fashing
*/
public class ListViewTest extends Application {
/**
* Informs the ListView that one of its items has been modified.
*
* @param listView The ListView to trigger.
* @param newValue The new value of the list item that changed.
* @param i The index of the list item that changed.
*/
public static <T> void triggerUpdate(ListView<T> listView, T newValue, int i) {
EventType<? extends ListView.EditEvent<T>> type = ListView.editCommitEvent();
Event event = new ListView.EditEvent<>(listView, type, newValue, i);
listView.fireEvent(event);
}
@Override
public void start(Stage primaryStage) {
// Create a list of mutable data. StringBuffer works nicely.
final List<StringBuffer> listData = Stream.of("Fee", "Fi", "Fo", "Fum")
.map(StringBuffer::new)
.collect(Collectors.toList());
final ListView<StringBuffer> listView = new ListView<>();
listView.getItems().addAll(listData);
final StackPane root = new StackPane();
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root));
primaryStage.show();
// Modify an item in the list every 2 seconds.
new Thread(() -> {
IntStream.range(0, listData.size()).forEach(i -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(listData.get(i));
Platform.runLater(() -> {
// Where the magic happens.
listData.get(i).append("!");
triggerUpdate(listView, listData.get(i), i);
});
});
}).start();
}
public static void main(String[] args) {
launch(args);
}
}
Bạn nên lấy danh sách quan sát và cập nhật đối tượng bằng cách sử dụng list.set (selectedIndex, đối tượng); Ví dụ của tôi hiển thị nút với phương pháp xử lý. Trong này tôi thay đổi nội dung người dùng danh sách trong fx viewtable
Button commit = new Button("Commit");
commit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent evt) {
int selectedIndex = tableView.getSelectionModel().getSelectedIndex();
User user = tableView.getSelectionModel().getSelectedItem();
user.setId(Integer.parseInt(idTF.getText()));
user.setName(nameCB.getValue());
user.setSurname(srnameTF.getText());
user.setAddress(addressTF.getText());
service.getUsers().set(selectedIndex, user);
tableView.toFront();
}
});
Sử dụng Francis ý tưởng tôi đã làm:
list.set(list.indexOf(POJO), POJO);
không thể là giải pháp tốt nhất nhưng làm việc.
Vì Java 8u60 ListView chính thức hỗ trợ phương thức refresh()
để cập nhật chế độ xem theo cách thủ công. JavaDoc:
Điều này rất hữu ích trong trường hợp nguồn dữ liệu cơ bản đã thay đổi theo cách không được quan sát bởi chính ListView.
Tôi đã sử dụng thành công phương pháp này cho vấn đề này tại đây để cập nhật nội dung của các mục trong ListView.
- 1. ListView Đang cập nhật một hàng
- 2. Thay đổi lớp CSS của một phần tử trên runtime
- 3. Android Listview không cập nhật
- 4. Id phần tử cập nhật jQuery
- 5. Android ListView cập nhật với SimpleCursorAdapter
- 6. Thay đổi ID của một phần tử bằng jQuery
- 7. Thay đổi phần tử của danh sách nếu nó giữ lại một số điều kiện hoặc thêm một phần mới nếu không, sử dụng Data.Lens
- 8. BaseAdapter.notifyDatasetChanged() không cập nhật ListView
- 9. JavaFX: Đang cập nhật phần UI trong một lớp điều khiển từ một chủ đề
- 10. Thay đổi phần tử lớp thành phần tử giao diện
- 11. C# Force ListBox để cập nhật các phần tử
- 12. Android: thông báoDataSetChanged() không cập nhật listview sau khi thay đổi hướng
- 13. listview không cập nhật với notifydatasetchanged() gọi
- 14. Cập nhật thiết lập C++ STL là tẻ nhạt: Tôi không thể thay đổi một phần tử tại vị trí
- 15. Cập nhật một dict với một phần của một dict
- 16. Nếu phần tử vượt quá một phần tử khác?
- 17. JavaFX - ràng buộc tài sản với các thuộc tính của mọi phần tử trong Bộ sưu tập quan sát
- 18. Sử dụng NSFetchedResultsControllerDelegate để cập nhật các phần & hàng của TableView sau khi thay đổi NSPredicate
- 19. Cập nhật một trường trong mỗi phần tử của mảng cấu trúc Matlab
- 20. Thay đổi thứ tự của các phần tử
- 21. Văn bản phần tử cập nhật jQuery html mà không ảnh hưởng đến các phần tử HTML của trẻ em
- 22. Di chuột một phần tử và thay đổi một phần tử khác (không sử dụng Javascript)
- 23. Android ListView Live Đang cập nhật
- 24. C# - Cập nhật một subitem trong một listview
- 25. Cập nhật văn bản của một phần tử với XSLT dựa trên thông số
- 26. Lấy phần tử đã chọn từ ListView
- 27. Cập nhật các phần tử trong Rails bằng Ajax
- 28. Chọn SQL: Cập nhật nếu có, Chèn nếu không - Với so sánh một phần ngày?
- 29. Tự động thay đổi bố cục hàng của một ListView
- 30. JavaFX - phong cách CSS listview
bạn có thể đăng lớp POJO u r không? – invariant
Có một cách tiếp cận được nêu tại Diễn đàn Oracle [ở đây] (https://forums.oracle.com/thread/2244635) mà phác thảo một giải pháp cho vấn đề này. – ThomasMH
Cách tiếp cận được đưa ra bởi kleopatra là giải pháp mới nhất và đơn giản nhất. Tôi muốn chỉ thêm rằng 'extractor' có thể trả về bất kỳ quan sát nào mà nó muốn. Và nó có thể được viết gọn gàng với lambdas. – HRJ