如何将嵌套员工的主管列表绑定到JavaFX 8中的单个组合框。
我与员工和主管有以下简单的类结构:
public class Employee
{
private final StringProperty nameProperty = new SimpleStringProperty();
public Employee(String name)
{
this.nameProperty.set(name);
}
public StringProperty nameProperty()
{
return this.nameProperty;
}
}
public class Supervisor
{
private final StringProperty nameProperty = new SimpleStringProperty();
private final ListProperty<Employee> employeesProperty = new SimpleListProperty<Employee>();
public Supervisor(String name, List<Employee> employees)
{
this.nameProperty.set(name);
this.employeesProperty.addAll(employees);
}
public StringProperty nameProperty()
{
return this.nameProperty;
}
public ListProperty<Employee> employeesProperty()
{
return this.employeesProperty;
}
}
最后是一个简单的静态Supervisor类:
public static class Supervisors
{
private static final ListProperty<Supervisor> supervisorsProperty = new SimpleListProperty<Supervisor>();
public static ListProperty<Supervisor> supervisorsProperty()
{
return supervisorsProperty;
}
}
(此示例的代码已经简化)
现在,我的问题是:
如何将主管列表绑定到JavaFX组合框(或列表视图,差异不应该重要)?我想&#34;展开&#34;员工列表,以便组合框项目如下所示:
Supervisor A
Employee A.1
Employee A.2
Supervisor B
Employee B.1
如果我只是将combobox.itemsProperty绑定到Supervisors.supervisorsProperty,那么我只会获得主管列表,而不是员工。
注意:我正在使用绑定,因此添加或删除主管或员工将直接反映在组合框中。
我是否使用特殊绑定或使用某种适配器类来展开&#34;展开&#34;将嵌套列表放入一个主管和员工列表中?如果是后者,那么我如何跟踪监督者列表(和嵌套员工)的变化,以及如何防止变为注册和未注册的变更登记者的复杂混乱?
PS:如果答案包含总是在组合框中显示主管/员工的正确名称的方式,那么有一个神奇的独角兽奖励积分 - 这样如果更改了名称,那么名称也会在组合框中更改
答案 0 :(得分:0)
我最终自己制作了糟糕而复杂的解决方案。
我为Supervisor和Employee添加了一个基类:
public abstract class NamedInstance {
private final StringProperty nameProperty = new SimpleStringProperty();
public NamedInstance(String name)
{
this.nameProperty.set(name);
}
public StringProperty nameProperty()
{
return nameProperty;
}
public String getName()
{
return nameProperty.get();
}
@Override
public String toString() {
return getName();
}
}
toString()将自动在ComboBox列表中使用。
然后我添加了这个糟糕的适配器类,用于制作嵌套的“带有员工的主管”结构的平面列表版本。在嵌套列表中添加或删除主管或员工时,平面列表将自动更改:
public class SupervisorsAndEmployeesList
{
// the flat list of supervisors and employees
private final ListProperty<NamedInstance> supervisorsAndEmployees = new SimpleListProperty<NamedInstance>(FXCollections.observableArrayList());
// a ChangeListener for changes in a list of Employees
private final ChangeListener<ObservableList<Employee>> employeeChangeListener = new ChangeListener<ObservableList<Employee>>()
{
@Override
public void changed(ObservableValue<? extends ObservableList<Employee>> observable,
ObservableList<Employee> oldValue, ObservableList<Employee> newValue)
{
refreshList();
}
};
public SupervisorsAndEmployeesList()
{
// add a ChangeListener for changes in the list of Supervisors
Supervisors.supervisorsProperty().addListener(new ChangeListener<ObservableList<Supervisor>>()
{
@Override
public void changed(
ObservableValue<? extends ObservableList<Supervisor>> observable,
ObservableList<Supervisor> oldValue,
ObservableList<Supervisor> newValue)
{
// make sure to have listeners on each employee, and to remove the listeners
// again when supervisors are removed
for (Supervisor supervisor : oldValue)
{
supervisor.employeesProperty().removeListener(employeeChangeListener);
}
for (Supervisor supervisor : newValue)
{
supervisor.employeesProperty().addListener(employeeChangeListener);
}
refreshList();
}
});
}
private void refreshList()
{
// clear the list and re-add all Supervisors and Employees.
// this is not effective, but more readable than keeping track
// a each change in the list
supervisorsAndEmployees.clear();
for (Supervisor supervisor : Supervisors.supervisorsProperty().get())
{
supervisorsAndEmployees.add(supervisor);
for (Employee employee : supervisor.employeesProperty().get())
{
supervisorsAndEmployees.add(employee);
}
}
}
public ListProperty<NamedInstance> supervisorsAndEmployeesProperty()
{
return supervisorsAndEmployees;
}
}
ComboBox项目设置如下:
supervisorsAndEmployeesComboBox.setItems(new SupervisorsAndEmployeesList().supervisorsAndEmployeesProperty().get());
处理这样一项任务的代码很多......
我还解决了在ComboBox中的名称发生更改的问题,然后Supervisor或Employee名称发生了变化,但我没有在上面包含该代码,因为这会使代码更加复杂和难以理解。通常,您只需“添加”一个“nameChangeListener”到每个Supervisor和Employee的nameProperty(记得也像删除employeeChangeListener一样删除监听器)。每次调用nameChangeListener时,都会调用“refreshList()”。