6

POJO でいっぱいの ListView があり、選択したアイテムの情報を GUI に表示するラベルが必要です。

私の POJO は次のようになります。

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

ユーザーがリストから顧客を選択すると、選択した顧客の名前がラベルに表示されます。

nameではないため、直接バインドすることはできませんPropertyString(そして、 CustomersをStringProperty-objectsに置き換えたくありません。これは、そうでSimpleStringPropertyはなく、 RMI 経由で転送serializableする必要があるためです。)Customer

私は次のようにJFXtrasBeanPathAdapterから(ちなみにとても素敵に見えます)を試しました:

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

しかし、このソリューションは私に例外をスローするだけです:

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

lstCustomers.getSelectionModel().selectedItemProperty().addListener(...)そこで、ラベルの人口を手動で使用して処理するよりも良い解決策があることを願っていました。

4

2 に答える 2

3

以前に提供したものよりも良い解決策は、試したように BeanPathAdapter を使用することです。
ただし、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; 
}

次に、コードに次のものが必要です。

BeanPathAdapter<Customer>  custBean;
custBean = new BeanPathAdapter<>( new Customer() );   // empty or any customer
custBean.bindBidirectional( "name", label.textProperty() );
custBean.beanProperty().bind( listview.getSelectionModel().selectedItemProperty() );
于 2013-12-18T10:59:15.797 に答える
1

あなたが探しているシンプルなワンライナーはないと思います。
次のことができます。

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

ただし、Customer POJO を次のように変更する必要があります。

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

    public ReadOnlyStringProperty nameProperty()
    {
        return new SimpleStringProperty( name );
    }
}

プロパティは基になるデータの変更を反映することが期待されており、上記は nameProperty が呼び出されたときの名前のみを反映するため、これはお勧めできません。そのため、setName が呼び出された場合、プロパティは変更を反映しません。顧客の名前が変わらない場合は、これを回避できます。

于 2013-12-18T08:59:18.760 に答える