【问题标题】:ChangeListener not fired unless source of ObjectProperty changed除非 ObjectProperty 的源发生更改,否则不会触发 ChangeListener
【发布时间】:2016-12-21 07:35:12
【问题描述】:

使用JavaFX8,如果ObjectProperty 的一个属性只有一个变化,但引用保持不变,怎么可能得到通知?

以下是使用ObjectProperty<KeyStore> 的具体示例。 java.security.KeyStore 包含密钥和证书的列表。如果添加、更改或删除条目,我希望收到通知。

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();
                    }
                }
            }
        }
    }
}

相关代码是第一次设置ObjectPropertys 值,然后删除一个元素。 changeListener 仅在设置 ObjectPropertys 值时收到通知,但在值更改时不会收到通知。

我的问题是:如果 KeyStore 得到更新,即使引用的对象没有改变,我如何才能获得通知? JavaFX 中是否有内置方式?

我的意图是在ListView 中显示所有包含的证书和密钥,并在每次从changeListener 中将证书添加或删除到KeyStore 时更新ListView。也许我完全走错了路,我应该完全不同?

附加信息:

this.getEntityController()

返回一个EntityController 的实例,该实例本身保存在ObjectProperty&lt;EntityController&gt; 中。

【问题讨论】:

    标签: java javafx observable


    【解决方案1】:

    我不知道更好的方法来处理这个限制,所以我所做的只是对修改后的对象执行 set(),这样引用保持不变,但更改会传播。

    【讨论】:

    • 你觉得编写一个简单的包装类的想法如何,它将每个方法调用转发到被包装的对象并触发PropertyChangeEvent?目前我也做了一个 set() 调用。
    • 我已经多次考虑过这个解决方案,但我总是认为它不值得。包装器的问题是您必须委托每个方法,因此维护成为一个问题。通过代理可能是可能的,但我认为这是一个矫枉过正。也许最好的方法就是创建一个实用程序,公开一个方法 forceChange() 来重新分配属性。
    • 这种方法似乎不再适用了。仅当 value != newValue 时,对象才被标记为无效
    猜你喜欢
    • 2019-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 2016-08-18
    相关资源
    最近更新 更多