UPDATE: + extremely primitive binding
Add an interface:
public interface Titlable { String getTitle(); StringProperty getProperty(); }
We add your classes:
public class Person implements Titlable { String name; int age; List<Work> works; List<Certificate> certificates; public String getTitle() { return name; } private StringProperty property; public StringProperty getProperty() { if (null == property) return property = new SimpleStringProperty( name + " " + age ); return property; } } public class Work implements Titlable{ String companyName; String positionName; int experienceAtMonth; public String getTitle() { return companyName; } private StringProperty property; public StringProperty getProperty() { if (null == property) return property = new SimpleStringProperty( companyName + " " + positionName ); return property; } } public class Certificate implements Titlable{ String organization; String position; Date date; public String getTitle() { return organization; } private StringProperty property; public StringProperty getProperty() { if (null == property) return property = new SimpleStringProperty( organization + " " + position + " " + date ); return property; } }
Actually the tree itself:
public class CustomTree extends TreeView<Titlable> { private final ObservableList<Person> persons; private final Main main; public CustomTree( ObservableList<Person> persons, Main main ) { this.persons = persons; this.main = main; TreeItem<Titlable> rootItem = new TreeItem<Titlable>(); rootItem.setExpanded( true ); this.setShowRoot( false ); this.setCellFactory( p -> new TreeCell<Titlable>() { @Override public void updateItem( Titlable t, boolean empty ) { super.updateItem( t, empty ); setText( t == null ? null : t.getTitle() ); } }); for ( Person p : persons ) { TreeItem<Titlable> pItem = new TreeItem<Titlable>( p ); rootItem.getChildren().add( pItem ); Titlable fake1 = new Titlable() { public String getTitle() { return "Works"; } private StringProperty property = new SimpleStringProperty( "-" ); }; Titlable fake2 = new Titlable() { public String getTitle() { return "Certificates"; } private StringProperty property = new SimpleStringProperty( "-" ); }; TreeItem<Titlable> f1Item = new TreeItem<Titlable>( fake1 ); TreeItem<Titlable> f2Item = new TreeItem<Titlable>( fake2 ); pItem.getChildren().addAll( f1Item, f2Item ); for ( Work w : p.works ) { f1Item.getChildren().add( new TreeItem<Titlable>( w ) ); } for ( Certificate c : p.certificates ) { f2Item.getChildren().add( new TreeItem<Titlable>( c ) ); } } setRoot( rootItem ); EventDispatcher originalDispatcher = this.getEventDispatcher(); this.setEventDispatcher( new NotExpandedEventDispatcher( originalDispatcher ) ); } private class NotExpandedEventDispatcher implements EventDispatcher{ private final EventDispatcher originDispatcher; public NotExpandedEventDispatcher( EventDispatcher originDispatcher ){ this.originDispatcher = originDispatcher; } @Override public Event dispatchEvent( Event event, EventDispatchChain tail ) { if ( event instanceof MouseEvent ) { if ( ((MouseEvent)event).getButton() == MouseButton.PRIMARY && ((MouseEvent)event).getClickCount() >= 2 ) { if ( !event.isConsumed() ) { TreeItem<Titlable> selectedItem = getSelectionModel().getSelectedItem(); main.doSomething( selectedItem .getValue() ); } event.consume(); } }else if ( event instanceof KeyEvent ){ if ( ((KeyEvent)event).getCode() == KeyCode.ENTER ){ if ( !event.isConsumed() ) { TreeItem<Titlable> selectedItem = getSelectionModel().getSelectedItem(); main.doSomething( selectedItem .getValue() ); } event.consume(); } } return originDispatcher.dispatchEvent( event, tail ); } } }
Checking:
public class Main extends Application { private TextArea ta; @Override public void start( Stage stage ) { ObservableList<Person> persons = FXCollections.<Person>observableArrayList(); Work work1 = new Work(); Work work2 = new Work(); Work work3 = new Work(); Work work4 = new Work(); Work work5 = new Work(); Work work6 = new Work(); Work work7 = new Work(); Work work8 = new Work(); work1.companyName = "roga i kapbIta 1"; work2.companyName = "roga i kapbIta 2"; work3.companyName = "roga i kapbIta 3"; work4.companyName = "roga i kapbIta 4"; work5.companyName = "roga i kapbIta 5"; work6.companyName = "roga i kapbIta 6"; work7.companyName = "roga i kapbIta 7"; work8.companyName = "roga i kapbIta 8"; Certificate certificate1 = new Certificate(); Certificate certificate2 = new Certificate(); Certificate certificate3 = new Certificate(); Certificate certificate4 = new Certificate(); certificate1.organization = "kapbIta i roga 1"; certificate2.organization = "kapbIta i roga 2"; certificate3.organization = "kapbIta i roga 3"; certificate4.organization = "kapbIta i roga 4"; Person a = new Person(); Person b = new Person(); Person c = new Person(); a.name = "ivan"; b.name = "da"; c.name = "mar'ya"; a.works = new ArrayList<>( Arrays.asList( work1, work2, work3 ) ); b.works = new ArrayList<>( Arrays.asList( work4, work5, work6 ) ); c.works = new ArrayList<>( Arrays.asList( work7, work8 ) ); a.certificates = new ArrayList<>( Arrays.asList( certificate1 ) ); b.certificates = new ArrayList<>( Arrays.asList( certificate2 ) ); c.certificates = new ArrayList<>( Arrays.asList( certificate3, certificate4 ) ); persons.addAll( a, b, c ); Parent container = new CustomTree( persons, this ); ta = new TextArea(); Scene scene = new Scene( new HBox( container, ta ) ); stage.setWidth( 650 ); stage.setHeight( 600 ); stage.setScene( scene ); stage.show(); } public static void main(String[] args) { launch(args); } public void doSomething( Titlable t ) { ta.textProperty().unbind(); ta.textProperty().bind( t.getProperty() ); } }
