2016-12-21 7 views
0

JavaFX8を使用して、ObjectPropertyの1つの属性のみが変更されても参照は同じままであれば、どのように通知することができますか?ObjectPropertyのソースが変更されない限り、ChangeListenerが起動しない

ObjectProperty<KeyStore>を使用した具体的な例に従います。 java.security.KeyStoreには、キーと証明書のリストが格納されています。エントリが追加、変更、削除された場合、通知を受けたい。 ObjectPropertyの値が最初に設定されます、その後、一つの要素が除去される

public abstract class EntityController { 
    protected ObjectProperty<KeyStore> trustStore = new SimpleObjectProperty<KeyStore>(); 

    public EntityController() { 

    } 

    public KeyStore getTrustStore() { 
     return this.trustStore.getValue(); 
    } 

    public void setTrustStore(KeyStore trustStore) { 
     this.trustStore.set(trustStore); 
    } 

    public ObjectProperty<KeyStore> trustStoreProperty() { 
     return this.trustStore; 
    } 


} 
public class CertificatesTabPresenter extends PKIPresenter implements Initializable { 

    @Override 
    public void initialize(URL arg0, ResourceBundle arg1) { 
      this.getEntityController().trustStoreProperty().addListener((observableVal, oldTrustStore, newTrustStore) -> { 
      trustStoreChanged(oldTrustStore, newTrustStore); 
     }); 
    } 


    @FXML 
    private void addTrustStore(MouseEvent e) { 
     File keyStoreFile = selectKeyStoreFile(); 
     if (keyStoreFile != null) { 
      Optional<String> keyStoreType = selectKeyStoreType(); 
      if(keyStoreType.isPresent()) { 
       Optional<char[]> password = insertPassword(); 
       if(password.isPresent()) { 
        try { 
         KeyStore trustStore = KeyStore.getInstance(keyStoreType.get()); 
         trustStore.load(null, null); 

         FileInputStream fis = new FileInputStream(keyStoreFile); 
         trustStore.load(fis, password.get()); 


         //This causes the changeListener to be notified because the reference changed 
         this.getEntityController().setTrustStore(trustStore); 


         //The changeListener won't be notified, because only the KeyStore changes internally but the reference stays the same 
         trustStore.deleteEntry(trustStore.aliases().nextElement()); 
         this.getEntityController().setTrustStore(trustStore); 
         //This also won't notify the changeListener 
         String a = this.getEntityController().getTrustStore().aliases().nextElement(); 
         this.getEntityController().getTrustStore().deleteEntry(a); 


        } catch (KeyStoreException e1) { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } catch (FileNotFoundException e1) { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } catch (NoSuchAlgorithmException e1) { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } catch (CertificateException e1) { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } catch (IOException e1) { 
         //TODO: password was wrong -> show error message 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } 
       } 
      } 
     } 
    } 
} 

関連するコードです。 changeListenerは、ObjectPropertyの値が設定されている場合にのみ通知されますが、値が変更された場合は通知されません。

私の質問は:KeyStoreが参照オブジェクトが変更されなくても更新された場合、どうすれば通知を受けることができますか? JavaFXには組み込みの方法がありますか?

私が意図しているのは、ListViewに含まれているすべての証明書とキーを表示し、証明書がchangeListener内からKeyStoreに追加または削除されるたびにListViewを更新することです。たぶん私は完全に間違った方法でやっていると私は完全に異なる必要がありますか?

追加情報:

this.getEntityController() 

ObjectProperty<EntityController>に保持され、それ自体EntityControllerのインスタンスを返します。

答えて

0

私はこの制限を扱うより良い方法を知らないので、参照が同じままだが変更は伝播するように、変更されたオブジェクトのset()を実行するだけです。

+0

ラップされたオブジェクトにすべてのメソッド呼び出しを転送し、 'PropertyChangeEvent'を発生させる単純なラッパークラスを書く考えはどう思いますか?現在私はset()呼び出しもしています。 –

+0

私はその解決策を何度か考えてきましたが、私はいつもそれが価値がないと思ってしまいます。ラッパーの問題は、すべてのメソッドを委任する必要があるため、保守が問題になることです。プロキシ経由では可能かもしれないが、私はそれが過度だと思う。 おそらく、プロパティの再割り当てを行うメソッドforceChange()を公開するユーティリティを作成するだけです。 – Rubasace

関連する問題