How to associate a JavaFX shortcut with a selected item from a ListView

I have a ListView full of POJOs and want the label in the GUI to display information from the selected item.

My POJO looks something like this:

class Customer { private String name; ... public String getName() { return name; } 

Now, when the user selects a customer from the list, I want the name of the selected customer to appear on the label.

Obviously, I cannot bind to name directly, because this is not Property . (And I don't want to replace my clients with String StringProperty objects, because SimpleStringProperty not serializable , and I need to pass Customer through RMI.)

I tried the BeanPathAdapter from JFXtras (which looks really nice by the way) as follows:

  BeanPathAdapter<MultipleSelectionModel> customerBeanPathAdapter; customerBeanPathAdapter = new BeanPathAdapter<>(lstCustomers.getSelectionModel()); customerBeanPathAdapter.bindBidirectional("selectedItem.name", lblCustomerName.textProperty()); 

But this solution only throws me an exception:

 ... Caused by: java.lang.IllegalArgumentException: Unable to resolve accessor getSelectedItem at jfxtras.labs.scene.control.BeanPathAdapter$FieldHandle.buildAccessor(BeanPathAdapter.java:3062) at jfxtras.labs.scene.control.BeanPathAdapter$FieldHandle.buildAccessorWithLikelyPrefixes(BeanPathAdapter.java:3022) at jfxtras.labs.scene.control.BeanPathAdapter$FieldHandle.updateMethodHandles(BeanPathAdapter.java:2986) at jfxtras.labs.scene.control.BeanPathAdapter$FieldHandle.<init>(BeanPathAdapter.java:2977) at jfxtras.labs.scene.control.BeanPathAdapter$FieldBean.performOperation(BeanPathAdapter.java:1348) at jfxtras.labs.scene.control.BeanPathAdapter$FieldBean.performOperation(BeanPathAdapter.java:1186) at jfxtras.labs.scene.control.BeanPathAdapter.bindBidirectional(BeanPathAdapter.java:567) at jfxtras.labs.scene.control.BeanPathAdapter.bindBidirectional(BeanPathAdapter.java:369) at at.gs1.sync.qm.client.gui.MainWindowController.initialize(MainWindowController.java:61) ... 22 more Caused by: java.lang.IllegalAccessException: symbolic reference class is not public: class javafx.scene.control.ListView$ListViewBitSetSelectionModel, from jfxtras.labs.scene.control.BeanPathAdapter$FieldHandle at java.lang.invoke.MemberName.makeAccessException(MemberName.java:512) at java.lang.invoke.MethodHandles$Lookup.checkSymbolicClass(MethodHandles.java:1113) at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1094) at java.lang.invoke.MethodHandles$Lookup.findVirtual(MethodHandles.java:626) at jfxtras.labs.scene.control.BeanPathAdapter$FieldHandle.buildAccessor(BeanPathAdapter.java:3049) ... 30 more 

So, I was hoping there would be a better solution than using lstCustomers.getSelectionModel().selectedItemProperty().addListener(...) and manually handle the tag population there.

+6
source share
2 answers

The best solution, I think, to what I gave earlier is to use the BeanPathAdapter as you tried.
However, the following property must be added for the BeanPathAdapter:

 private final ObjectProperty<B> beanProp = new SimpleObjectProperty<>(); { beanProp.addListener( new ChangeListener<B>() { @Override public void changed( ObservableValue<? extends B> ob, B oldVal, B newVal ) { setBean( newVal ); } } ); } public ObjectProperty<B> beanProperty() { return beanProp; } 

Then in your code you need the following:

 BeanPathAdapter<Customer> custBean; custBean = new BeanPathAdapter<>( new Customer() ); // empty or any customer custBean.bindBidirectional( "name", label.textProperty() ); custBean.beanProperty().bind( listview.getSelectionModel().selectedItemProperty() ); 
+2
source

I do not think that there is a simple one liner that you are looking for.
You can do the following:

 label.textProperty().bind( Bindings.selectString( listview.getSelectionModel().selectedItemProperty(), "name" ) ); 

But you will need to change your POJO client so:

 class Customer { private String name; ... public String getName() { return name; } public ReadOnlyStringProperty nameProperty() { return new SimpleStringProperty( name ); } } 

I do not think this is recommended, because the properties are expected to reflect changes in the underlying data, and the above will only reflect the name, as it was when calling nameProperty. So if setName is called, the property will not reflect the change. If the Customer’s name never changes, you can handle it.

+1
source

Source: https://habr.com/ru/post/953131/


All Articles