Статьи

JavaFX 2.0 бета-пример приложения и после мыслей

Я довольно давно играл с JavaFX и имел хороший и плохой опыт использования этого языка. С выходом бета-версии JavaFX 2.0 я решил попробовать.

Здесь я разработал простое приложение геокодирования, которое получит адрес и предоставит значения широты и долготы для этого местоположения — используя API геокодирования Google.

Я использовал Groovy для синтаксического анализа JSON, поскольку последняя версия 1.8 обеспечивает действительно удобную поддержку синтаксического анализа JSON.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import groovy.json.*
  
class GeocodingParser {
  static def GEOCODE_JSON_URL = "http://maps.googleapis.com/maps/api/geocode/json"
  static def GEOCODE_XML_URL = "http://maps.googleapis.com/maps/api/geocode/xml"
  
  static def getGeocodeForAddress(address){
    def queryBuilder = []
    queryBuilder << "address=${URLEncoder.encode(address)}"
    queryBuilder << "sensor=false"
    def queryString = queryBuilder.join("&")
    def requestUrl = GEOCODE_JSON_URL+"?${queryString}"
    def payload = new URL(requestUrl).text
    def jsonSlurper = new JsonSlurper()
    def doc = jsonSlurper.parseText(payload)
    def geocode = new Geocode()
    geocode.latitude = doc.results.geometry.location.lat.join("")
    geocode.longitude = doc.results.geometry.location.lng.join("")
    geocode.locationType = doc.results.geometry.location_type.join("")
    return geocode
  }
}
  
class Geocode {
  def String latitude
  def String longitude
  def String locationType
  def String toString(){
    return "Latitude: ${latitude}, Longitude:${longitude} and Location type: ${locationType}"
  }
}

Вы можете видеть, что анализ json с использованием JsonSlurper настолько лаконичен. Анализатор groovy возвращает значения широты, долготы и типа местоположения (это значения, представляющие интерес для нашего приложения) в классе-обёртке Geocode, который снова является компонентом Grooy.

Теперь давайте посмотрим на код JavaFX, который на самом деле является сутью этого поста:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
public class NewFXMain extends Application {
  
 /**
 * @param args the command line arguments
 */
 public static void main(String[] args) {
   Application.launch(NewFXMain.class, args);
 }
  
 @Override
 public void start(Stage primaryStage) {
   primaryStage.setTitle("Geocoder");
   TabPane mainTabPane = new TabPane();
   Tab geoTab = new Tab("Geocoding");
   geoTab.setClosable(false);
   mainTabPane.getTabs().add(geoTab);
  
   final GridPane geoGrid = new GridPane();
   geoGrid.setHgap(10);
   geoGrid.setVgap(10);
   geoGrid.setPadding(new Insets(0, 20, 0, 10));
  
   Label mainGeoLabel = new Label("Geocoding");
  
   final TextBox geoAddressTextBox = new TextBox(15);
  
   Button geoCodeButton = new Button("Geocode");
   final TextBox latitudeValTextBox = new TextBox();
   latitudeValTextBox.setEditable(false);
   final TextBox longitudeValTextBox = new TextBox();
   longitudeValTextBox.setEditable(false);
   final TextBox locationTypeValTextBox = new TextBox();
   locationTypeValTextBox.setEditable(false);
  
   final StringProperty latitudeProperty = new StringProperty();
   latitudeProperty.addListener(new ChangeListener<String>() {
  
     @Override
     public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
       latitudeValTextBox.setText(newValue);
     }
   });
  
   final StringProperty longitudeProperty = new StringProperty();
   longitudeProperty.addListener(new ChangeListener<String>() {
  
     @Override
     public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
       longitudeValTextBox.setText(newValue);
     }
   });
  
   final StringProperty locationTypeProperty = new StringProperty();
   locationTypeProperty.addListener(new ChangeListener<String>() {
  
     @Override
     public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
       locationTypeValTextBox.setText(newValue);
     }
   });
  
   geoCodeButton.setOnAction(new EventHandler<ActionEvent>(){
  
     @Override
     public void handle(ActionEvent event) {
       String address = geoAddressTextBox.getText();
       if(address == null){
       }else{
         Geocode parsedCode = (Geocode)GeocodingParser.getGeocodeForAddress(address);
         latitudeProperty.set(parsedCode.getLatitude());
         longitudeProperty.set(parsedCode.getLongitude());
         locationTypeProperty.set(parsedCode.getLocationType());
      }
    }
   });
  
   geoGrid.add(mainGeoLabel, 4, 1);
   geoGrid.add(new Label("Address"), 2, 3);
   geoGrid.add(geoAddressTextBox, 3, 3,3,1);
   geoGrid.add(new Label("Latitude"), 2,7);
  
   geoGrid.add(new Label("Longitude"),2,8);
  
   geoGrid.add(new Label("Location Type"),2,9);
   geoGrid.add(latitudeValTextBox,3,7,2,1);
   geoGrid.add(longitudeValTextBox,3,8,2,1);
   geoGrid.add(locationTypeValTextBox,3,9,2,1);
   geoGrid.add(geoCodeButton, 4, 5);
   geoTab.setContent(geoGrid);
   Scene scene = new Scene(mainTabPane);
   primaryStage.setScene(scene);
   primaryStage.setVisible(true);
   primaryStage.setResizable(false);
 }
}

Я использовал привязки, чтобы связать компонент, отображающий значения типа широта, долгота и местоположение, со свойствами для тех же значений. Например, код ниже показывает, как значение широты было привязано к элементу управления, который будет отображать значение. Этот элемент управления (текстовое поле) содержит значение широты, полученное после передачи ответа json, отправленного API геокодирования.

Теперь мы создаем StringProperty для хранения значения для широты и прикрепляем слушатель изменения к этому свойству так, чтобы при каждом обновлении значения в этом свойстве мы обновляли текстовое поле новым значением. Итак, что именно меняет значение этого свойства? Мы добавляем кнопку, которая вызывает анализатор groovy и получает значения типа широты, долготы и местоположения в классе-оболочке. В обработчике действия выше мы получаем проанализированные значения и затем обновляем свойства соответствующими значениями. Это обновление, в свою очередь, вызывает метод в соответствующих слушателях изменений.

Теперь перейдем к макету для элементов управления. Я использовал макет GridBox, и это было действительно гибко, так как это позволило мне расположить компоненты в аккуратном порядке.

Вот несколько после мыслей:

  • JavaFX 2.0 был изменен, чтобы сделать его более дружественным к Java-программисту
  • JavaFX 2.0 более многословен, чем сценарий JavaFX, например: посмотрите, как должны выполняться привязки.
  • Недостаток инструментальной поддержки. Создание графического интерфейса затруднительно.
  • Программисты Java не должны изучать новый язык все вместе, они будут чувствовать себя как дома с API JavaFX
  • Совместимость с другими языками JVM, такими как Groovy, Scala.
  • Много новых элементов управления, API добавлены в JavaFX 2.0.
  • Отсутствие мультиплатформенной поддержки.

Исходный код можно найти здесь .

Ссылка: пример приложения с использованием бета-версии JavaFX 2.0 и послесвечения от нашего партнера по JCG Мохамеда Санауллы в блоге Experiences Unlimited .

Статьи по Теме :