位于上海,服务全国!

位于上海,服务全国!

了解Java的Observable和JavaFX的Observable

作者:admin 分类: 时间:2016-08-18 16:38:33 点击量:2872

Observable及Observer对象在执行Java的模型 - 视图 - 控制器的结构具有重要作用。 他们通常在系统中使用,有一个对象需要通知其他相关的一些重要变化的发生。Observable是一个类和Observer是一个接口。 它们可以在java.util包内作为Java核心工具框架的一部分被找到。 然而,在JavaFX中找到Observable的实体是一个接口,并且是javafx.beans包的一部分。 其基本的思路是一样的,但在执行会有变化。

Java的Observable和Observer

扩展类可以在程序的其他部分由其他感兴趣的类进行观察。登记类被通知,只要任何变化被触发在可被观察的类中,而被观察到的类被注册。 这是可观察的类和观察类之间的关系。 Observer类只是Observer接口的实现。 该Observer接口提供了update()方法,当一个观察者被通知在所观察到对象中的变化。

如果它已经改变了,想要被观察到的一个类,或者扩展Observable类必须调用setChanged方法,必须通过调用notifyObservers()方法触发通告。 这反过来又调用观察者类的update()方法。 然而,如果一个对象调用notifyObserver()方法,而不调用setChanged()方法,没有动作会发生。 因此,可观察到的对象必须调用setChange()方法之前去调用notifyObservers()方法以针对任何事件变化。 该命令随后将无缝调用观察者类的update()方法。

一个简单的举例
该举例给出了如何观测和可观测实现的观点。 该PeopleObserver类执行Observer接口,以及PeopleObservable类扩展Observable类。 PeopleObservable对象被监测,通过由PeopleObserver类定义的可观察到的的列表进行。 一旦在观察的类出现一个变化时,它通知观察员作为观察对象被添加到列表中的addObserver()方法。 每次调用notifyObserver()触发调用观察者随后的update()方法。

package org.mano.example;

import java.util.Observable;
import java.util.Observer;


public class PeopleObserver implements Observer {


   private String name;


   public PeopleObserver() {
      super();
   }


   public PeopleObserver(String name) {
      super();
      this.name = name;
   }


   public String getName() {
      return name;
   }


   public void setName(String name) {
      this.name = name;
   }


   @Override
      public void update(Observable o, Object arg) {
         System.out.println(name + " got " +
            ((Integer) arg).intValue() + " winks");
      }


}


package org.mano.example;


import java.util.Observable;


public class PeopleObservable extends Observable {


   private String name;


   public PeopleObservable() {
      super();
   }


   public PeopleObservable(String name) {
      this.name = name;
   }


   public String getName() {
      return name;
   }


   public void setName(String name) {
      this.name = name;
   }


   void wink(int count) {
      setChanged();
      notifyObservers(count);
   }
}


package org.mano.example;


import java.util.Random;


public class Main {


   public static void main(String[] args) {


      PeopleObservable damsel = new PeopleObservable("Minnie");


      PeopleObserver mickey = new PeopleObserver("Mickey");


      PeopleObserver donald = new PeopleObserver("Donald");


      PeopleObserver guffy = new PeopleObserver("Goofy");


      damsel.addObserver(mickey);
      damsel.addObserver(donald);
      damsel.addObserver(goofy);


      System.out.println("There are " + damsel.countObservers()
                                      + " observers of "
                                      + damsel.getName());


      Random r = new Random();
      damsel.wink(r.nextInt(10));
   }
}




JavaFX的Observable
JavaFX的Observable接口是许多容器类的基本接口和JavaFX收集框架的接口。 例如,ObservableList和ObservableArray是两个基本Observable接口的常见实现。 Java核心集API已经包含了许多有用的容器类来代表通用的数据结构列表,设置和地图。 例如,java.util.ArrayList是一个可重组的数组实现的java.util.List接口以包含对象的列表。 然而,它们不能无缝的工作,当同步的功能被要求在列表模型和在GUI场景视图组件之间。


在JavaFX之前,Swing开发人员依靠ArrayList包含对象的列表,并随后以列表如UI控制,如JList来显示它们。 但是,ArrayList是太普通了,并且没有内置牢记同步的要求,当与视图组件相关联时。 其结果是,相当困难进行更新,添加,或从型号列表中删除对象,并同时反映视图组件的变化。 为了克服这个问题,JavaFX使用可观察到的接口及其实现,如ObserverList。


由于ObservableList坚持MVC的观察到的和观察范式的规则,如它提供的通知关于任何从型号列表对象中选择更新,添加或删除感兴趣的观察者,它成为一个事实上的容器使用任何列出了JavaFX的舞台。 在这里,在该模型数据表示和图被无缝同步。  JavaFX的ObserverList典型的应用于UI控件,如ListView和TableView。 让我们通过一个简单的例子来看看如何实际使用ObservableList。


这是一个简单举例,在此数据列表显示在被称为ListView 的JavaFXUI控制内。 所使用的隐含数据模型是ObservableList。 有两个ListView控制用于将数据从一个控制移动到另外一个,以及两个ObservableLists代表底层模型的数据。 数据不仅在视觉上从一个控制移动到另一个,但它也从一个模型移动到另一个。 这使得视图和模型层之间实现同步数据转换。


package org.mano.example;


import javafx.application.Application;
import javafx.collections.*;
import javafx.event.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;


public class ObservableListdemo extends Application {


   private final ObservableListcountries;
   private final ObservableListcapitals;


   private final ListViewcountriesListView;
   private final ListViewcapitalsListView;


   private final Button leftButton;
   private final Button rightButton;


   public ObservableListdemo() {
      countries = FXCollections.observableArrayList("Australia",
         "Vienna", "Canberra", "Austria", "Belgium","Santiago",
         "Chile", "Brussels", "San Jose", "Finland", "India");
      countriesListView = new ListView<>(countries);
      capitals = FXCollections.observableArrayList("Costa Rica",
         "New Delhi", "Washington DC", "USA", "UK", "London",
         "Helsinki", "Taiwan", "Taipei", "Sweden", "Stockholm");
      capitalsListView = new ListView<>(capitals);


      leftButton = new Button(" < ");
      leftButton.setOnAction(new ButtonHandler());


      rightButton = new Button(" > ");
      rightButton.setOnAction(new ButtonHandler());


   }


   public static void main(String[] args) {
      launch(args);
   }


   @Override
   public void start(Stage primaryStage) {
      primaryStage.setTitle("Arrange Countries and Capitals");
      BorderPane root = new BorderPane();
      Scene scene = new Scene(root, 500, 450);


      GridPane gridPane = new GridPane();
      gridPane.setPadding(new Insets(5));
      gridPane.setHgap(10);
      gridPane.setVgap(10);
      ColumnConstraints column1 = new ColumnConstraints(150, 150,
         Double.MAX_VALUE);
      ColumnConstraints column2 = new ColumnConstraints(50);
      ColumnConstraints column3 = new ColumnConstraints(150, 150,
         Double.MAX_VALUE);
      column1.setHgrow(Priority.ALWAYS);
      column3.setHgrow(Priority.ALWAYS);
      gridPane.getColumnConstraints().addAll(column1, column2, column3);


      Label countriesLabel = new Label("Countries");
      GridPane.setHalignment(countriesLabel, HPos.CENTER);
      gridPane.add(countriesLabel, 0, 0);


      Label capitalsLabel = new Label("Capitals");
      GridPane.setHalignment(capitalsLabel, HPos.CENTER);
      gridPane.add(capitalsLabel, 2, 0);


      gridPane.add(countriesListView, 0, 1);
      gridPane.add(capitalsListView, 2, 1);


      VBox vbox = new VBox();
      vbox.getChildren().addAll(rightButton, leftButton);


      gridPane.add(vbox, 1, 1);


      root.setCenter(gridPane);
      GridPane.setVgrow(root, Priority.ALWAYS);
      primaryStage.setScene(scene);
      primaryStage.show();
   }


   private class ButtonHandler implements EventHandler{


   @Override
   public void handle(ActionEvent event) {


      if (event.getSource().equals(leftButton)) {
         String str = capitalsListView.getSelectionModel()
            .getSelectedItem();
         if (str != null) {
            capitals.remove(str);
            countries.add(str);
         }
      } else if (event.getSource().equals(rightButton)) {
         String str = countriesListView.getSelectionModel()
            .getSelectedItem();
         if (str != null) {
            countriesListView.getSelectionModel().clearSelection();
            countries.remove(str);
            capitals.add(str);
         }
      }
   }
}
Observable类和Observer接口

图形1.' 前面的代码输出

结论
Observable类和Observer接口提供了一个非常宝贵的推动力来实现基于模型 - 视图 - 控制器模式的复杂程序架构。 实际上,可观察到的和观察者概念不仅仅是MVC的。 一个很好理解的基本概念可以帮助创建更复杂的Java代码。 如果观察者和可观察到的部分Java核心程序框架展示原则,JavaFX可观察到的类和接口恰好表明这些原则如何能投入工作。


原文:

http://www.developer.com/java/data/understanding-java-observable-and-javafx-observable.html