Yahoo에서 일기 예보 받기!

By Sergey Malenkov, November 11, 2008

이 간단한 JavaFX 어플리케이션은 Yahoo! Weather RSS 공급자를 통해 받아온 일기 예보를 보여준다. 어떤 위치든 그 위치의 ID로 요청이 될 수 있다. 예를 들면, Tallinn (Estonia)은 ENXX0004, St. Petersburg (Russia)는 RSXX0091, Prague (Czech Republic)는 EZXX0012, Menlo Park는 USCA0693,그리고 Santa Clara는 USCA1018 이다.

코드 이해하기

이 예제는 JavaFX 프로그래밍 언어에서 XML을 parse하는 방법을 보여준다.

일기 예보에 대한 정보는 그림 1과 같이, JavaFX 비동기 HTTP API 를 사용하여 HTTP GET 요청을 수행함으로써 얻게 된다. 오류가 발생하더라도 input stream은 닫히게 됨에 주목 하라.

Source Code
      HttpRequest {
        location: url
        onDone: function() {
          // check for errors after parsing
          if (forecast.isEmpty()) 
            location = "Loading error"
        }
        onInput: function(input) {
          try {
            // parse input stream
            // see Figure 2
          } finally {
            input.close()
          }
        }
      }.enqueue()
  

그림 1: 일기 예보 요청

응답 받는 문서는 JavaFX XML pull parser로 정보에서 위치와 그 위치의 예보를 뽑아내어 분류한다. 예제 코드는 그림 2와 같다.

Source Code
            PullParser {
              var wind: Wind;
              var temp: String;
              var speed: String;
              input: input
              onEvent: function(event) {
                if ((event.type == PullParser.START_ELEMENT) and (event.qname.prefix == "yweather")) {
                  if (event.qname.name == "location") {
                    location = event.getAttributeValue(QName{name:"city"});
                    def region = event.getAttributeValue(QName{name:"region"});
                    if (0 < region.length()) {
                      location = "{location}, {region}"
                    }
                  }
                  else if (event.qname.name == "units") {
                    temp  = event.getAttributeValue(QName{name:"temperature"});
                    speed = event.getAttributeValue(QName{name:"speed"})
                  }
                  else if (event.qname.name == "wind") {
                    wind = Wind {
                      angle: event.getAttributeValue(QName{name:"direction"})
                      speed: event.getAttributeValue(QName{name:"speed"})
                      unit:  speed
                    }
                  }
                  else if (event.qname.name == "condition") {
                    insert Forecast {
                      day: "Now"
                      high: event.getAttributeValue(QName{name:"temp"})
                      text: event.getAttributeValue(QName{name:"text"})
                      code: event.getAttributeValue(QName{name:"code"})
                      unit: temp
                      wind: wind
                    } into forecast
                  }
                  else if (event.qname.name == "forecast") {
                    insert Forecast {
                      day:  event.getAttributeValue(QName{name:"day"})
                      low:  event.getAttributeValue(QName{name:"low"})
                      high: event.getAttributeValue(QName{name:"high"})
                      text: event.getAttributeValue(QName{name:"text"})
                      code: event.getAttributeValue(QName{name:"code"})
                      unit: temp
                    } into forecast
                  }
                }
              }
            }.parse()
  

그림 2: 서버 응답에서 분류

코드 변형

Config class는 날씨 위젯(widget)의 형태에 영향을 주는 다음과 같은 변수를 포함한다.

WIDTH
위젯의 우선시되는 넓이, 단 실제 넓이는 화면 넓이에 종속된다
HEIGHT
위젯의 높이
SPACE
구성요소들 간의 기본 여백
SMALL_FONT
작은 글씨에 사용된 폰트: 예보 이름, 기온, 풍속
LARGE_FONT
큰 글씨에 사용된 폰트: 위치와 간단한 설명
(자동으로 계산된다)
ROUND
사각형의 네 모퉁이의 호의 지름
FONT_COLOR
모든 글씨에서 사용된 전경색
DARK_COLOR
주 배경색
LIGHT_COLOR
gradient 채우기 생성시 밝은쪽 배경색

Source Code
public def WIDTH = 320;
public def HEIGHT = 170;

public def SPACE = 2;
public def SPACE_DOUBLE = 2 * SPACE;

public def SMALL_FONT = Font {
  size: 12
}
public def LARGE_FONT = Font {
  size: SPACE + 2 * SMALL_FONT.size
}

public def ROUND = SMALL_FONT.size;
public def OFFSET = HEIGHT - 6 * SPACE - 2 * LARGE_FONT.size;

public def FONT_COLOR  = Color.WHITE;
public def DARK_COLOR  = Color.DARKBLUE;
public def LIGHT_COLOR = Color.LIGHTBLUE;
  

그림 3: 변경 할 변수들