我有一个观察者
成员类由一个Person(以及其他不重要的值,因为它们不会出现在表视图中)组成。每个
Person
都有一个StringProperty
name和一个ObjectProperty
tableview应该在第一列显示人的名字,在第二列显示狗的名字。如下所示:示例表视图
我设法通过绑定两个
TableColiv来实现这一点
现在,我还必须使用
组合框
es,通过它,用户可以更新表视图
所选行中的名称。因此,我在所选项和组合框的valueProperty()
之间创建了绑定。
如果通过组合框更改了人员名称,则表视图会更新该单元格,而狗名称的单元格不会自动显示新值。我知道这是因为
成员
没有收到关于狗属性更改的通知。但是我还没有找到一个解决方案,如何让一个对象意识到它的子对象中的变化。
所以我想,概括地说,我的问题是(1)如何在平面表格视图中显示嵌套对象,以及(2)如果任何(潜在的)嵌套属性发生变化,如何自动更新表格视图。
示例代码:
package sample;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.util.StringConverter;
public class ControllerString {
private class Dog
{
private final StringProperty name;
public Dog(String name) {
this.name = new SimpleStringProperty(name);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
}
private class Person
{
private final StringProperty name;
private final ObjectProperty<Dog> dog;
public Person(String name, Dog dog) {
this.name = new SimpleStringProperty(name);
this.dog = new SimpleObjectProperty<>(dog);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public Dog getDog() {
return dog.get();
}
public ObjectProperty<Dog> dogProperty() {
return dog;
}
public void setDog(Dog dog) {
this.dog.set(dog);
}
}
private class Member
{
private final ObjectProperty<Person> person;
public Member(Person person) {
this.person = new SimpleObjectProperty<>(person);
}
public Person getPerson() {
return person.get();
}
public ObjectProperty<Person> personProperty() {
return person;
}
public void setPerson(Person person) {
this.person.set(person);
}
}
@FXML
private TableView<Member> membersTableView;
@FXML
private TableColumn<Member, Person> nameTableColumn;
@FXML
private TableColumn<Member, Person> dogTableColumn;
@FXML
private ComboBox<Person> nameComboBox;
@FXML
private ComboBox<Dog> dogComboBox;
private final ObservableList<Member> members = FXCollections.observableArrayList();
@FXML
private void initialize()
{
nameTableColumn.setCellValueFactory(cellData -> cellData.getValue().personProperty());
nameTableColumn.setCellFactory(column -> new TableCell<Member, Person>() {
@Override
protected void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
setContentDisplay(ContentDisplay.TEXT_ONLY);
if(person == null || empty)
{
setText(null);
}
else
{
setText(person.getName());
}
}
});
dogTableColumn.setCellValueFactory(cellData -> cellData.getValue().personProperty());
dogTableColumn.setCellFactory(column -> new TableCell<Member, Person>()
{
@Override
protected void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
setContentDisplay(ContentDisplay.TEXT_ONLY);
if(person == null || empty)
{
setText(null);
}
else
{
setText(person.getDog().getName());
}
}
});
nameComboBox.setConverter(new StringConverter<Person>() {
@Override
public String toString(Person person) {
if(person == null)
{
return null;
}
return person.getName();
}
@Override
public Person fromString(String name) {
return new Person(name, new Dog("Puppy"));
}
});
dogComboBox.setConverter(new StringConverter<Dog>() {
@Override
public String toString(Dog dog) {
if(dog == null)
{
return null;
}
return dog.getName();
}
@Override
public Dog fromString(String name) {
return new Dog(name);
}
});
membersTableView.getSelectionModel().getSelectedItems().addListener((ListChangeListener<Member>) change -> {
while(change.next()) {
if(change.wasRemoved()) {
Member oldValue = change.getRemoved().get(0);
nameComboBox.valueProperty().unbindBidirectional(oldValue.personProperty());
}
if(change.wasAdded()) {
Member newValue = change.getAddedSubList().get(0);
nameComboBox.valueProperty().bindBidirectional(newValue.personProperty());
}
}
});
nameComboBox.valueProperty().addListener(((observable, oldValue, newValue) -> {
if(oldValue != null) {
dogComboBox.valueProperty().unbindBidirectional(oldValue.dogProperty());
}
if(newValue != null)
{
dogComboBox.valueProperty().bindBidirectional(newValue.dogProperty());
}
}));
membersTableView.setItems(members);
members.add(new Member(new Person("Bob", new Dog("Caesar"))));
}
}
如果将人
和狗
的可见性修改为公共
,绑定。select
可与cellValueFactory
s一起使用,它允许您摆脱定制的TableCell
实现:
public class Dog {
...
}
public class Person {
...
}
...
@FXML
private TableColumn<Member, String> nameTableColumn;
@FXML
private TableColumn<Member, String> dogTableColumn;
...
@FXML
private void initialize() {
nameTableColumn.setCellValueFactory(cellData -> Bindings.select(cellData.getValue().personProperty(), "name"));
dogTableColumn.setCellValueFactory(cellData -> Bindings.select(cellData.getValue().personProperty(), "dog", "name"));
...
但是,如果其中一个中间属性可以包含null
,则可能会导致大量警告。。。
假设我们有以下集合,我对此没有什么问题: > 我想增加“item_name”的价格:“my_item_two”,如果它不存在,应该将它追加到“items”数组中。
我正在尝试更新MongoDB中嵌套对象中的一个键值。目前,我的做法是覆盖整个嵌套对象,我如何改变一个键-值对?
我需要更新嵌套在我的用户文档中的一个字段,该字段包含一个part对象数组,以添加新的part。一个part对象如下所示: 所以这意味着$addToset对我的情况没有好处...现在我不知道该怎么办。
谁能告诉我我在这里做错了什么?从console.log,我可以看到日期功能正在正常工作。但是,即使在之后,时间戳也不会更新。提前感谢!
我知道我不是第一个问这个的,但是我在前面的问题中找不到答案。我有一个组件 在控制器中,会不时发生变化。 在中,数据以表格格式作为HTML输出。每当发生更改时,此值就会发生更改。 我的组件需要使用作为触发器在Google Map上重绘标记。问题是,当在父级中更改时,ngOnChanges不会激发。我能做什么? 更新:ngOnChanges不工作,但看起来像是正在更新lapsData。在ngInit中
问题内容: 是否可以在sql中执行更新语句,但仅在更新不同时才执行更新? 例如 如果在数据库中, 不应 执行任何类型的更新 但是,如果 这 应该 执行更新。 问题答案: 使用更新前触发器可以做到这一点。在此触发器中,您可以将旧值与新值进行比较,并在新值不变的情况下取消更新。但这将导致呼叫者网站上的错误。 我不知道为什么要这样做,但是这里有几种可能性: 性能:这里没有性能提升,因为更新不仅需要找到正