Добавление прослушивателя к переменной в Java / JavaFX, которая вызывается при изменении переменной
5 ответов
так просто:
public void changeBooleanFlag(boolean bEnabled)
{
if(booleanFlag == bEnabled) return;
booleanFlag = bEnabled;
myFunc();
}
и всякий раз, когда вы хотите изменить флаг типа boolean, вы должны сделайте это с помощью этого метода.
Если вы используете JavaFX 2, то он предоставляет готовые решения для архитектуры компонентов JavaBeans и Шаблона дизайна наблюдателя. Кроме того, это дает большую гибкость связывания состояния переменных привязками свойств. В приведенном ниже коде показаны события изменения свойств и привязка переменных свойств. Конечно, вы можете обернуть аксессоры свойств, чтобы скрыть детали, как 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<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> 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<ActionEvent>() {
@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<PropertyChangeListener> 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);
}
}
U может использовать шаблон проектирования 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<Listener> listeners = new ArrayList<Listener>();
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..
}
}
есть 2 решения вашей проблемы
- используя простую Java, в этом случае вы должны добавить слушателей в свой bean (самостоятельно), а затем вызвать методы прослушивателя в методе setter (снова самостоятельно) и сделать переменную частная, поэтому его можно изменить только с помощью метода setter.
- второе решение использует чистую структуру AOP (я знаю, что AspectJ может это сделать), которая может перехватить модификацию вашей переменной, а затем вызвать ваш слушатель использует аспект. Я упомяну, что с помощью @AspectJ (поддержка аннотаций AspectJ) ваши аспекты будут чистыми классами Java, и нет необходимости поддерживать IDE AspectJ.