繁体   English   中英

如何将JavaFX Label绑定到ListView中的选定项目

[英]How to bind a JavaFX Label to the selected item from a ListView

我有一个装满POJO的ListView,并希望GUI中有一个标签来显示所选项目的信息。

我的POJO看起来像这样:

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

现在,当用户从列表中选择客户时,我希望在标签中显示所选客户的名称。

显然我不能直接绑定到name ,因为它不是Property (而且我不想用StringProperty -objects替换我的Customers String ,因为SimpleStringProperty不可serializable ,我需要通过RMI传输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(...)并手动处理那里的标签填充。

我认为,对于之前给出的更好的解决方案是使用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() );

我不认为你正在寻找一个简单的衬垫。
您可以执行以下操作:

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

但您需要修改您的客户POJO,如下所示:

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

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

我不认为这是推荐的,因为预期属性会反映基础数据的变化,而上述内容只会反映调用nameProperty时的名称。 因此,如果调用setName,则属性不会反映更改。 如果客户名称永远不会改变,那么您可以逃避这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM