将侦听器添加到Java / JavaFX中的变量,该变量在变量变量时被调用

我知道JavaFX中有听众,我确信Java。 但我很困惑如何实现它们。

我有一个在我的程序中更改的布尔变量。 每次更改布尔值时,我都希望运行一个函数myFunc()。

这可以轻松完成吗?

就这么简单:

public void changeBooleanFlag(boolean bEnabled) { if(booleanFlag == bEnabled) return; booleanFlag = bEnabled; myFunc(); } 

每当你想改变布尔标志时,你应该通过这种方法来做。

如果您使用的是JavaFX 2,那么它为JavaBeans组件体系结构和Observer设计模式提供了现成的解决方案。 此外,它通过属性绑定提供了很大的灵活性,可以将变量状态相关联。 下面的代码说明了属性更改事件和属性变量的绑定。 当然,你可以通过下面的getFlag()setFlag()包装属性访问器来隐藏细节,并在其余的应用程序中使用它们。

 public class Demo extends Application { private BooleanProperty booleanProperty = new SimpleBooleanProperty(true); public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { // Add change listener booleanProperty.addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { System.out.println("changed " + oldValue + "->" + newValue); myFunc(); } }); Button btn = new Button(); btn.setText("Toggle boolean flag"); btn.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { booleanProperty.set(!booleanProperty.get()); //toggle System.out.println("toggled to " + booleanProperty.get()); } }); // Bind to another property variable btn.underlineProperty().bind(booleanProperty); StackPane root = new StackPane(); root.getChildren().add(btn); primaryStage.setScene(new Scene(root, 300, 250)); primaryStage.show(); } public boolean getFlag() { return booleanProperty.get(); } public void setFlag(boolean val) { booleanProperty.set(val); } } 

我会使用PropertyChangeListener来做到这一点。 这是一个很好的教程: http : //docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html

代码示例:

 import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; public class MyClass { private final List listeners = new ArrayList<>(); private boolean b1, b2; public MyClass() { } public boolean isB1() { return b1; } public void setB1(boolean b1) { boolean oldValue = this.b1; this.b1 = b1; firePropertyChange("b1", oldValue, b1); } public boolean isB2() { return b2; } public void setB2(boolean b2) { boolean oldValue = this.b2; this.b2 = b2; firePropertyChange("b2", oldValue, b2); } public void addPropertyChangeListener(PropertyChangeListener listener) { listeners.add(listener); } private void firePropertyChange(String property, Object oldValue, Object newValue) { for (PropertyChangeListener l : listeners) { l.propertyChange(new PropertyChangeEvent(this, property, oldValue, newValue)); } } /** * Main method for tests. * @param args */ public static void main(String[] args) { MyClass m = new MyClass(); m.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent e) { String changedProperty = e.getPropertyName(); System.out.println("Changed property: " + changedProperty); System.out.println("New value: " + e.getNewValue()); System.out.println("Old value: " + e.getOldValue()); System.out.println(); } }); m.setB1(true); m.setB2(false); } } 

你可以使用Observer设计模式。 像这样:

  public interface Listener { public void handle(Object o) ; } public class PropertiesChangeListener { public void handle(Object o) { //DO SOMETHING... } } public class Bean { private boolean flag; private List listeners = new ArrayList(); public setFlag(boolean flag) { this.flag = flag; if (listeners.size() > 0 ) { for (Listener l : this.listeners ) { l.handle(flag); //invoke } } } public registerListener(Listener listener) { this.listeners.add(listener); } //..... other fields and methods } public class Main{ public static void main(String[] args) { Bean bean = new Bean(); bean.registerListener(new PropertiesChangeListener()); bean.setFlag(true); //handler method will be invoked.. } } 

有两种解决方案可以解决您的问题

  1. 在这种情况下,使用普通Java,你应该为你的bean添加监听器(你自己),然后在setter方法上调用监听器方法(再由你自己),并使变量私有 ,所以它只能由你的setter修改方法。
  2. 第二种解决方案是使用纯AOP框架(我知道AspectJ可以做到这一点),它可以拦截变量的修改,然后使用方面调用你的监听器。 我将提到使用@AspectJ(AspectJ的注释支持),您的方面将是纯Java类,并且不需要AspectJ支持IDE。