お天気情報WebAPIを使ってGIF画像を表示する

2012年1月27日(金)
PROJECT KySS

お天気の情報とGIF画像を表示する処理

[<<]と[>>]ボタンタップで増減するメンバ変数noの値で、条件分岐を行います。noの値が0の時は、メンバ変数myNowにtoday(今日)を格納し、[<<]ボタンを使用不可に、[>>]ボタンを使用可とします。1の時は、myNowにtomorrow(明日)を格納します。2の時は、myNowにdayaftertomorrow(明後日)を格納し、[<<]ボタンを使用可能に、[>>]ボタンを使用不可とします。
メンバ変数noの値をAddDaysメソッドに指定し、短いタイプの日付を変数myDateに格納します。指定した日数を加算、減算するのにDateTimeのインスタンスからAddDaysメソッドを使用します。
ImageTools.IO.Decoders.AddDecoder(Of GifDecoder)()
の1文を追加します。これはGIFを表示させるために、初期化の際に一度だけ必要な処理です。このまま覚えてください。
新しいExtendedImageクラスのインスタンス、myImageオブジェクトを作成します。ExtendedImageクラスは、Image クラスのピクセルを格納し、ファイルやストリームのサイズ変更やカッティングのような操作から、イメージを読み込む機能を提供するクラスです。
各市のお天気情報を表示するには、各市のidが必要です。このidは
http://weather.livedoor.com/forecast/rss/forecastmap.xml
から取得することができます。上記URLに移動してブラウザの「ソースの表示(V)」を選択して、ソースを表示させると、図3のような構造のXMLになっています。この中の<city>要素の”id”属性の値を取得する必要があります。

図3:forecastmap.xmlの構造(クリックで拡大)
 Uri型の変数myUriにhttp://weather.livedoor.com/forecast/rss/forecastmap.xmlのUriを格納しておきます。新しいWebClientのインスタンスmyWebClientオブジェクトを作成します。DownloadStringAsyncメソッドで、Uri として指定したリソースをダウンロードします。
AddHandler ステートメントでダウンロードが完了した DownloadStringCompleted イベントに、イベント ハンドラを追加します。イベント ハンドラ内では、ダウンロードされた文字列としての結果 XML(resultArgs.Result) をXElement.Parseメソッドで文字列として読み込みます。読み込んだXMLの<city>要素の”title”属性の値が、cityTextBox.Textの値と同じ<city>要素を選択するクエリを定義します。そのクエリ内を反復処理しながら変数resultに各要素を格納していきます。メンバ変数cityIdに<city>要素の属性”id”の値を格納します。数値型のメンバ変数myIdに数値に変換したcityIdの値を格納します。
新しいWebClientのインスタンス、wcオブジェクトを作成します。お天気情報のAPI へのリクエストは、対象となる「市」や表示する「日」などの条件を下記のような URL で指定します。(REST)
Dim _uri As Uri = New Uri(String.Format("http://weather.livedoor.com/forecast/webservice/rest/v1?city={0}&day={1}", myId, myNow), UriKind.Absolute)
cityには、先に取得した「市」のidが入ります。dayには変数myNowの値が入ります。myNowの値はメンバ変数noの値によって、today(今日)、tomorrow(明日)、dayaftertomorrow(明後日)と変化します。DownloadStringAsyncメソッドに、上記Uriを指定しソースをダウンロードします。
cityに「松山」のidである104を指定し、dayに「今日」を表すtodayを指定すると、図4のようなXMLが返ってきます。<image>要素の子要素<url>を見るとGIF画像が指定されています。ImageToolsを使用しなければ、この画像はWindows Phoneでは表示できません。

図4:結果XML(クリックで拡大)
AddHandler ステートメントでダウンロードが完了した DownloadStringCompleted イベントに、イベント ハンドラを追加します。イベント ハンドラ内では、ダウンロードされた文字列としての結果 XML(myresultArgs.Result) をXElement.Parseメソッドで文字列として読み込みます。変数areaに、最初に見つかった<title>要素の値を格納します。地域名が格納されます。areaTextBlock内に変数areaの内容と、日付を格納した変数myDateの値を連結して表示します。
変数weatherに<Image>要素の子要素<title>要素の値を格納します。天気情報が格納されます。weatherTextBlockに変数weatherの値を表示します。変数gifUriに<image>要素の子要素<url>の値を格納します。お天気のGIF画像のURLが格納されます。ExtendedImageクラスのインスタンスである、myImageのUriSourceプロパティにgifUriのUriを絶対Uriで指定します。UriSourceプロパティでは、ExtendedImageのUriのソースを設定できます。Try~Catch~End Tryで例外処理を行います。例外が発生した場合はメッセージを表示し、[>>]ボタンの使用を不可として処理を抜けます。
GIF画像の読み込みが完了した時に発生する、LoadingCompletedイベントに、イベントハンドラを追加します。イベントハンドラ内では、Image1のSourceプロパティに、ExtendedImageクラスのインスタンス、myImageオブジェクトをBitmapに変換して指定しています。GIF画像を表示するには、Dispatcherが関連付けられているスレッドで、デリゲートを実行する必要があります。これには、非同期処理であるBeginInvokeメソッドを使用します。
  Private Sub DataShow()
    Select Case no
      Case 0
        myNow = "today"
        prevButton.IsEnabled = False
        nextButton.IsEnabled = True
      Case 1
        myNow = "tomorrow"
      Case 2
        myNow = "dayaftertomorrow"
        nextButton.IsEnabled = False
        prevButton.IsEnabled = True
    End Select
 
    Dim myDate As String= DateTime.Now.AddDays(no).ToShortDateString
    
    ImageTools.IO.Decoders.AddDecoder(Of GifDecoder)()
 
    Dim myImage As ExtendedImage = New ExtendedImage
    
    Dim myUri As Uri = New Uri("http://weather.livedoor.com/forecast/rss/forecastmap.xml", UriKind.Absolute)
 
    Dim myWebClient As New WebClient
    myWebClient.DownloadStringAsync(myUri)
 
    AddHandler myWebClient.DownloadStringCompleted, Sub(resultSender As Object, resultArgs As DownloadStringCompletedEventArgs)
                Dim xmldoc As XElement = XElement.Parse(resultArgs.Result)
                Dim query = From c In xmldoc.Descendants("city") Where c.Attribute("title").Value.Equals(cityTextBox.Text) Select c
                For Each result In query
  
                cityId = result.Attribute("id").Value
                myId = Integer.Parse(cityId)
              Next
 
                Dim wc As New WebClient
                Dim _uri As Uri = New Uri(String.Format("http://weather.livedoor.com/forecast/webservice/rest/v1?city={0}&day={1}", myId, myNow), UriKind.Absolute)
        wc.DownloadStringAsync(_uri)
        AddHandler wc.DownloadStringCompleted, Sub(myresultSender As Object, myresultArgs As DownloadStringCompletedEventArgs)
      Try                                                                                                    
        Dim doc As XElement = XElement.Parse(myresultArgs.Result)
        Dim area As String = doc.Descendants("title").First.Value
        areaTextBlock.Text = area & "(" & myDate & ")"
        Dim weather As String = doc.Descendants("image").Elements("title").Value
        weatherTextBlock.Text = weather
        Dim gifUri As String = doc.Descendants("image").Elements("url").Value
        myImage.UriSource = New Uri(gifUri, UriKind.Absolute)
      Catch
        MessageBox.Show("市が不正です。")
        no = 0
        nextButton.IsEnabled = False
        Exit Sub
      End Try
    End Sub
  End Sub
      AddHandler myImage.LoadingCompleted, Sub(loadSender As Object, loadArgs As EventArgs)
                Dispatcher.BeginInvoke(Sub()
                  Image1.Source = myImage.ToBitmap
                                           End Sub)
              End Sub
  End Sub

[>>]ボタンがタップされた時の処理

メンバ変数noの値が2の場合はnoの値は2とします。それ以外の場合は、メンバ変数noの値を1ずつ増加させます。[>>]ボタンの使用を可能とします。お天気情報を表示するDataShowプロシージャを実行します。
  Private Sub nextButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles nextButton.Click
    If no = 2 Then
       no = 2
    Else
       no = no + 1
       nextButton.IsEnabled = True
    End If
    DataShow()
  End Sub

[<<]ボタンがタップされた時の処理

メンバ変数noが0の場合はnoの値は0とします。それ以外の場合は、メンバ変数noの値を1ずつ減少します。[<<]ボタンの使用を可能とします。お天気情報を表示するDataShowプロシージャを実行します。
  Private Sub prevButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles prevButton.Click
    If no = 0 Then
       no = 0
    Else
       no = no - 1
       prevButton.IsEnabled = True
    End If
    DataShow()
  End Sub
End Class
  • 「お天気情報WebAPIを使ってGIF画像を表示する」のサンプルプログラム

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています