簡體   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