読者です 読者をやめる 読者になる 読者になる

xin9le.net

Microsoft の製品/技術が大好きな Microsoft MVP な管理人の技術ブログです。

Rx入門 (21) - Webの画像をスライド表示

Rx

今回は、Web上の画像をダウンロードしてスライドショー形式で表示するサンプルを紹介します。先日自然気胸で入院していたときに@ch3cooh先生作のWindows Phone 7アプリ某時計に触発されて作ったものの一部で、super bijin-tokeiの画像を3秒間隔 (1分間隔でなく3秒間隔ですよ!) で表示します。通信エラーなどは一切考慮されていないのはご愛嬌です。

サンプルコード

以下にXAMLのコードを示します。画像を表示するための領域が指定されているだけの簡単なものです。

<Window x:Class="Sample40_SlideShow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Sample40_SlideShow" Height="400" Width="500">
    <Image Name="display" />
</Window>

次に、画像をダウンロードして表示する部分のコードを示します。美人時計の画像URLは時間毎に生成できるので、00:00~23:59までをループして処理します。それをThreadPool上で3秒間隔でひとつずつダウンロードし、UIスレッド上でビットマップを生成して表示する、という流れになっています。

using System;
using System.Linq;
using System.Net;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Media.Imaging;
 
namespace Sample40_SlideShow
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
 
            //--- 00:00 ~ 23:59の値を生成
            (from hour in Enumerable.Range(0, 24)
             from minute in Enumerable.Range(0, 60)
             select new{ Hour = hour, Minute = minute })
            .ToObservable(Scheduler.ThreadPool) //--- ThreadPoolで発行
            .Repeat() //--- ずっと繰り返す
            .Select((time, index) =>
            {
                //--- 最初を除いて3秒待機
                if (index != 0)
                    Thread.Sleep(3000);
 
                //--- 画像をダウンロード
                var format      = "http://www.bijint.com/jp/tokei_images/{0:00}{1:00}.jpg";
                var url         = string.Format(format, time.Hour, time.Minute);
                var request     = WebRequest.Create(url) as HttpWebRequest;
                request.Referer = "http://www.bijint.com/jp/";
                return request.GetResponse().GetResponseStream();
            })
            .ObserveOn(SynchronizationContext.Current) //--- UIスレッドに戻す
            .Subscribe(stream =>
            {
                //--- ビットマップを生成して表示
                var bitmap = new BitmapImage();
                bitmap.BeginInit();
                bitmap.StreamSource = stream;
                bitmap.EndInit();
                this.display.Source = bitmap;
            });
        }
    }
}

ほぼほぼ先の説明通りの実装になっていることが確認できると思います。したい処理の流れ通りの実装ができていることは、コード上の雑念が少ないということで非常に歓迎すべきものです。

実行例

実行すると以下のようになります。これで可愛い女の子をストレス無く (?) 大量に見ることができますね!そして、こんなに簡単に書けるなんて、Rx実に素晴らしい!

SlideShow

これに画像の自動保存機能を付ければ、1日分1440枚を短時間で取得できてしまうというちょっと悪いこともできます。また、サンプルコード集にはもう少し男の子が喜びそうな機能を付けましたので、ぜひダウンロードしてお楽しみ下さいw (ぇ