Добавление слушателя к переменной в Java / JavaFX, которая вызывается при изменении переменной - PullRequest
8 голосов
/ 02 апреля 2012

Я знаю, что в JavaFX есть слушатели, и я уверен, что Java.Но я не совсем понимаю, как их реализовать.

У меня есть логическая переменная, которая изменяется во всей моей программе.Каждый раз, когда изменяется логическое значение, я хочу, чтобы функция myFunc () запускалась.

Можно ли это сделать легко?

Ответы [ 5 ]

24 голосов
/ 02 апреля 2012

Если вы используете 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<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);
    }
}
4 голосов
/ 15 декабря 2012

Я бы сделал это, используя 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);
    }
}
4 голосов
/ 02 апреля 2012

Как просто:

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

и всякий раз, когда вы хотите изменить логический флаг, вы должны сделать это с помощью этого метода.

1 голос
/ 02 апреля 2012

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..
      }
  }
0 голосов
/ 02 апреля 2012

Есть 2 решения для вашей проблемы

  1. Используя обычную Java, в этом случае вы должны добавить слушатели к вашему бину (самостоятельно) и затем вызвать методы слушателя в методе setter (сновасамостоятельно) и сделайте переменную private , чтобы ее можно было изменить только с помощью вашего метода установки.
  2. Второе решение - использование чистого AOP-фреймворка (я знаю, AspectJ может это сделать), который может перехватить модификацию вашей переменной, а затем вызвать вашего слушателя, используя аспект.Я упомяну, что при использовании @AspectJ (поддержка аннотаций AspectJ) вашими аспектами будут чистые классы Java, и в IDE поддержки AspectJ нет необходимости.
...