2014-09-19 17 views
8

Mi chiedevo come associare valori in cui l'origine del bind potrebbe essere nullo.Associazione JavaFX e valori nulli

Ho un immobile:

private ObjectProperty<Operation> operation = new SimpleObjectProperty<>(null); 

Ho anche un campo di testo:

@FXML 
private Text txtCurrentOperation; 

vorrei legare il textProperty del campo al valore dell'oggetto dell'operazione.

Il mio primo pensiero è stato quello di utilizzare FluentAPI con la sua quando/then/altrimenti costruire, ma è con entusiasmo valutato quindi la soluzione:

Bindings.when(operation.isNotNull()) 
    .then("null") 
    .otherwise(operation.get().getName())); 

lancerà una NPE, perché il parametro di otherwise viene valutata non importa qual è il risultato dello when.

La mia prossima idea era di usare in qualche modo lambda:

txtCurrentOperation.textProperty().bind(() -> 
     new SimpleStringProperty(
      operation.isNotNull().get() ? "Null" : operation.get().getName() 
      )); 

Ma l'associazione non ha soluzione lambda abilitato. (In seguito mi sono reso conto che non poteva avere, perché il vero lavoro va all'indietro: la modifica dell'oggetto bindato (operazione) attiverà l'aggiornamento del raccoglitore (la proprietà text del campo))

Alcuni articoli che ho trovato suggerito di utilizzare un valore "estremo" per la proprietà anziché null. Ma Operation è un componente complesso e pesante quindi non è banale costruire un'istanza artificiale per rappresentare nulla. Ancor di più, questo mi sembra boilercode, qualcosa che il meccanismo vincolante è progettato per aiutare a eliminare.

Il mio prossimo tentativo era di scambiare logicamente la direzione del binding e aggiungere listener alla proprietà dell'operazione e lasciare che aggiornasse il campo in modo programmatico. Funziona e piuttosto semplice finché la necessità di aggiornamento dipende solo le istanze di oggetti operazione: getta:

operation.addListener((e) -> { 
     txtCurrentOperation.setText(operation.isNull().get() ? 
      "Null" : operation.get().getName()); 
}); 
operation.set(oper); 

E 'relativamente semplice, ma non funziona "Un valore limite non può essere impostato." eccezione e non vedo perché la proprietà testuale del controllo sia considerata vincolata.

Ho esaurito le idee. Dopo molte ricerche, non riesco ancora a risolvere il semplice problema di aggiornare un campo di testo in modo diverso a seconda che la fonte sia nullo o meno.

Questo sembra un problema così semplice e quotidiano, che sono sicuro di aver perso la soluzione.

risposta

6

Se una libreria di terze parti è un'opzione, controllare EasyBind. Provare qualcosa di simile:

EasyBind.select(operation) 
     .selectObject(Operation::nameProperty) 
     .orElse("null"); 

C'è anche un JavaFX JIRA issue per il tipo di funzionalità fornite da EasyBind. Se non si desidera utilizzare una libreria di terze parti, provare Bindings.select:

Bindings.when(operation.isNotNull()) 
    .then("null") 
    .otherwise(Bindings.select(operation, "name")); 

essere consapevoli del nullo il check-in Bindings.select non è super efficiente. C'è un JIRA issue for it.

+0

Grazie per entrambe le soluzioni. Nonostante il piccolo errore di battitura sul secondo codice (una parentesi chiusa errata dopo la selezione (parte operazione) funziona alla grande.Io ho letto l'articolo sull'inefficienza ma non è un problema a questo punto, a causa del singolo legame che sarebbe cambio di rado Inoltre ho controllato la libreria e sembra promettente, quindi forse ci provo anche io. – Balage1551

+0

Inoltre, un'altra soluzione con lambda (che si trova nell'esempio di EasyBind, ma non ha bisogno della libreria): 'txtCurrentOperation. textProperty(). bind (Bindings.createStringBinding (() -> operation.isNull(). get()? "null": operation.get(). getName(), operation)); ' – Balage1551

+0

Questo ha risolto il problema con un Salva il pulsante per il mio editor. L'API è interrotta qui –

0

Nel caso in cui qualcuno non utilizzi Java stesso ma Kotlin. È una buona idea usare la meravigliosa libreria tornadofx. Qui puoi semplicemente usare operation.select{it.name}. Anche se questa funzione sembra non essere ancora stata documentata, ci è voluto del tempo per scoprirla.

+0

Questa è una domanda javafx. Non una domanda javafx vs kotlin. – JRichardsz

+0

@JRichardsz, il javafx è lo stesso sia per java che per kotlin. Il mio punto è che se per qualche motivo ko tlin, c'è una soluzione molto buona al problema. Tornadofx è solo una libreria su javafx. – Darksnake