2014-06-23 24 views
0

에서 중첩 된 목록은 어떻게 자바 FX의 단일 콤보 상자에 중첩 된 직원과 감독자의 목록을 결합 할 8자바 FX - 콤보

나는 직원 및 감독자 다음과 같은 간단한 클래스 구조가 있습니다

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; 
    } 
} 

최종적 간단한 정적 감시 등급 :

public static class Supervisors 
{ 
    private static final ListProperty<Supervisor> supervisorsProperty = new SimpleListProperty<Supervisor>(); 

    public static ListProperty<Supervisor> supervisorsProperty() 
    { 
     return supervisorsProperty; 
    } 
} 

(이 코드는 예를 들어 간소화 된) 0

이제 내 질문은 :

어떻게하면 수퍼바이저 목록을 JavaFX 콤보 박스 (또는 목록보기, 차이는 중요하지 않음)에 바인딩 할 수 있습니까? 난 그냥 나는 그냥 목록을 얻을 것이라고는 Supervisors.supervisorsProperty에 combobox.itemsProperty을 결합하면

Supervisor A 
Employee A.1 
Employee A.2 
Supervisor B 
Employee B.1 

: 나는 콤보 상자 항목은 다음과 같이 할 수 있도록, 직원의 목록을 "전개"하고 싶은 관리자가 아닌 직원.

참고 : 추가 또는 제거 감독자 또는 직원이 콤보 상자에 직접 반영 될 수 있도록 바인딩을 사용하고 있습니다.

중첩 목록을 수퍼바이저 및 직원의 단일 목록으로 "펼치기"위해 특수 바인딩을 사용하거나 어댑터 클래스를 사용합니까? 후자의 경우 수퍼바이저 목록 (및 중첩 된 직원)의 변경 사항을 어떻게 추적합니까? 그리고 변경 기록원이 등록 및 등록 취소되는 복잡한 난제가되지 않도록하려면 어떻게해야합니까?

추 신 : 콤보 박스에 표시되는 감독자/직원의 정확한 이름을 항상 포함하는 방법이 포함 된 경우 마법 유니콘 보너스 포인트가 표시됩니다. 이름이 변경되면 이름도 변경됩니다. 콤보 박스.

+0

같은 ComboBox에서 감독자와 직원을 찾고 있습니까? – ItachiUchiha

+0

예. 아마 그것의 이름 속성을 가진 감독자와 직원 모두를위한 공유베이스 _Person_ 클래스가 필요할 것이므로 ComboBox 이 될 것입니다. 그러나 제 두통은 실제로 어떻게 바인딩을 만드는 지요? (멋지고 깨끗한 방법으로 if 가능하면 콤보 박스와 수퍼바이저 및 중첩 된 직원 목록이 있습니까? 이 작업을 수행하는 간단한 방법이 있습니까? 아니면 해당 목록을 플랫 Person 목록에 "펼치고"바인딩해야합니까? (이것은 필요 이상으로 복잡해 보입니다. 그리고 평평한 목록을 최신으로 유지하는 것에 대해 생각해야합니다) –

답변

0

나는 끔찍하고 복잡한 해결책을 스스로 만들었습니다.

나는 관리자와 직원 모두에 대한 기본 클래스를 추가 :

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().

그런 다음 중첩 된 "직원이있는 감독자"구조의 플랫 목록 버전을 만들기 위해이 끔찍한 어댑터 클래스를 추가했습니다.

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; 
    } 
} 

콤보 상자 항목은 다음과 같이 설정됩니다 : 평면 목록이 자동으로 감독자 또는 직원이 중첩 된 목록에서 추가 또는 제거 할 때 변경됩니다 코드의

supervisorsAndEmployeesComboBox.setItems(new SupervisorsAndEmployeesList().supervisorsAndEmployeesProperty().get()); 

엄청 많이 처리하는 등 작업 ...

관리자 나 직원 이름이 변경 될 때마다 ComboBox가 변경 될 때 문제가 해결되었지만 위의 코드는 포함시키지 않았습니다. 코드가 훨씬 복잡해지고 읽을 수 없습니다. 일반적으로 각 Supervisor 및 Employee의 nameProperty에 "nameChangeListener"를 "추가"합니다 (employeeChangeListener와 마찬가지로 리스너도 제거해야 함). nameChangeListener가 호출 될 때마다 "refreshList()"를 호출합니다.