SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ComponentZine(ComponentOne)

WPFのビットマップ効果を使ったチャート表示アプリケーションを作る

ComponentOne Studio Enterprise 2008J(SP2)のChart for WPFコンポーネントで華麗なグラフを表示(その2)

  • このエントリーをはてなブックマークに追加

 Chart for WPFコンポーネントは、WPF(Windows Presentation Foundation )の持つ高品質な 2-D/3-D グラフィックス表示やアニメーション機能を生かすことができるようになっています。 特にビットマップ視覚効果では、単純なピクセル処理操作ではあるものの、シャドウやべベル、グロウなどの視覚効果をチャートの要素に適用でき、さらにこの視覚効果をアニメーションさせることができます。 また、作成したグラフを画像ファイルに保存することができるので、他のアプリケーションとグラフを画像データとして共有できます。 そこで、前回の記事「データをグラフ表示するWPFアプリケーションを作る 」で作成したグラフに、さらに視覚効果とそのアニメーション機能を追加し、作成したグラフをファイルに保存する機能を組み込んでみました。

  • このエントリーをはてなブックマークに追加

はじめに

 Chart for WPFコンポーネントは、WPF(Windows Presentation Foundation )の持つ高品質な2-D/3-Dグラフィックス表示やアニメーション機能を生かすことができるようになっています。

 特にビットマップ視覚効果では、単純なピクセル処理操作ではあるものの、シャドウやべベル、グロウなどの視覚効果をチャートの要素に適用でき、さらにこの視覚効果をアニメーションさせることができます。

 また、作成したグラフを画像ファイルに保存できるので、他のアプリケーションと作成したグラフを画像データとして共有できます。

 そこで、今回は以前の記事「データをグラフ表示するWPFアプリケーションを作る」で作成したグラフに、視覚効果とアニメーション機能を追加し、さらに作成したグラフをファイルに保存する機能を組み込んでみました。

ビットマップ効果でさらにグラフを装飾する
ビットマップ効果でさらにグラフを装飾する
作成したグラフをファイルに保存できる
作成したグラフをファイルに保存できる
PNG形式の画像で保存
PNG形式の画像で保存

対象読者

 Visual Basic/Visual C# 2008を使ってプログラムを作ったことのある人

必要な環境

 Visual Basic 2008、Visual C# 2008、Visual Studio 2008でプログラムが作れる環境。なお、本プログラムはWindows Vista上で動作するVisual Studio 2008を使用して作成し、動作確認を行っています。

プログラム実行時の注意事項

 Chart for WPFを使って作成したアプリケーションを配布する場合、Chart for WPFのアセンブリファイルを添付する必要があります。これは、Common Language RuntimeのDLLをアプリケーションと一緒に配布するのと同じです。アプリケーションを正常に動作させるためには、次のファイルをインストールする必要があります。

インストールするファイル
ファイル 内容
C1.WPF.C1Chart.dll C1WPFChartコントロール

 このファイルを、プログラムを実行するフォルダに格納します。.NET Framework 3.0/3.5から追加されたクラスやメンバを使用しているので、.NET Framework 3.0/3.5以上のバージョンの.NET Frameworkがインストールされていることが必須条件です。

コンポーネントのインストール

 はじめてChart for WPFコンポーネントを使用する方は、Visual Studio、Visual Basic、Visual C#の開発環境にComponentOne Studio Enterprise 2008Jをインストールする必要があります。

 インストーラは、グレープシティのWebページからダウンロードできます。製品ページの[申込フォーム]をクリックし、グレープシティのWebサイトへ必要情報を登録すると、添付トライアルライセンスキーファイルとダウンロードサイトを記載したE-Mailが送られてきますので、ここからダウンロードします。制限事項などの詳細については、インストーラに同梱されているリリースノートを参照ください。

コントロールの追加

 ComponentOne Studio Enterprise 2008Jをインストールしたら、ツールボックスに専用のタブを作成し、使用するコンポーネントを追加します。追加するコンポーネントは、「WPFコンポーネント」のアセンブリ名が「C1.WPF.C1Chart」のコンポーネント「C1Chart」です。

アセンブリ名が「C1.WPF.C1Chart」のコンポーネント「C1Chart」を選択する
アセンブリ名が「C1.WPF.C1Chart」のコンポーネント「C1Chart」を選択する

グラフ要素の変更

 まずは、全体的にグラフの要素を変更します。ボーダーをチャートとタイトルに分け、それぞれ背景の塗りつぶしグラデーションも2つに分けます。

変更前
変更前
変更後
変更後

データの変更

 グラフの元データを入れ替えます。もともと、デフォルトで設定されていたデータは5つしかなかったので、もう少し増やして凡例の名前も付けます。

 この作業は、「Window1.xaml」の<c1chart:ChartData.ItemNames>と<c1chart:DataSeries>タグの値を入れ替えるだけです。

修正前
<c1chart:ChartData.ItemNames>P1 P2 P3 P4 P5</c1chart:ChartData.ItemNames>
<c1chart:DataSeries Label="Series 1" Values="20 22 19 24 25" SymbolFill="CadetBlue" />
<c1chart:DataSeries Label="Series 2" Values="8 12 10 12 15" SymbolFill="Crimson" />
修正後
<c1chart:ChartData.ItemNames>2001 2002 2003 2004 2005 2006 2007 2008</c1chart:ChartData.ItemNames>
<c1chart:DataSeries Label="営業収入" Values="266001 274889 275863 274312 272334 268632 262338 252918" 
					SymbolFill="CadetBlue" />
<c1chart:DataSeries Label="営業費用" Values="262987 262358 269332 268585 266547 265939 264409 264423" 
                    SymbolFill="Crimson" />  

ボーダーの追加と背景色のグラデーション作成

 次に、チャートのボーダーの中に入れていたタイトルを抜き出し、専用のボーダーを設定します。背景色のグラデーションもチャートとは変え、区別します。

 操作としては、今あるボーダーをタイトル専用にして、チャートに新たにボーダーを設定します。そのために、もう1つグラデーションのStyleタグを作成します。ボーダーとグラデーションに使用する色は「BlueViolet」です。

 「Application.xaml(C#はApp.xaml)」を開き、既に作成してあるStyleタグをコピー&ペーストし、Keyとカラーネームを変更します。

Application.xamlの追加コード
<Style x:Key="chart_border2" TargetType="{x:Type Border}">
    <Setter Property="BorderBrush" Value="BlueViolet"/>
    <Setter Property="CornerRadius" Value="5"/>
    <Setter Property="BorderThickness" Value="2"/>
    <Setter Property="Margin" Value="2"/>
    <Setter Property="Padding" Value="2"/>
    <Setter Property="Background">
        <Setter.Value>
            <LinearGradientBrush Opacity="0.25" StartPoint="0,0" EndPoint="1,1">
                <GradientStop Color="Transparent" Offset="0"/>
                <GradientStop Color="BlueViolet" Offset="1"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

 次に、「Window1.xaml」に戻り、デザイン画面でボーダーをドラッグしてタイトル周りに設定しなおします。また、TextBlockのサイズもボーダーに合わせます。

ボーダーをドラッグしてタイトル周りに設定する
ボーダーをドラッグしてタイトル周りに設定する

 そして、<c1chart:C1Chart>タグの前に、新しい<Border>タグを作成します。Styleプロパティには、今作成したBlueVioletのグラデーション-ボーダーを指定します。

Window1.xamlの追加コード
<Border Style="{StaticResource chart_border2}" Margin="12,45,12,12">
        <c1chart:C1Chart Margin="37,67,73.5,87" Name="c1Chart1" Background="Transparent" Palette="Metro">
		............
		... 中略 ...
		............
        </c1chart:C1Chart>
</Border>

 デザイン画面でボーダーをドラッグして、チャート周りにボーダーを設定します。これで、タイトルとチャートを2つに分離できました。

 ついでに、CheckBoxも上に移動させます。

チャート周りにボーダーを設定する
チャート周りにボーダーを設定する

ビットマップ視覚効果の設定

 次に、チャートにドロップシャドウ、べベル、アウトグロウという3つの視覚効果を設定します。

WPFのビットマップ視覚効果

 これらの視覚効果は、WPFのビットマップ視覚効果機能を用いて設定します。

 ドロップシャドウは既にタイトルのテキストに施していますが、光が当たった時の影を設定する視覚効果です。影の方向、色、ぼかしの程度、影の深さをプロパティで設定します。今回は、テキストに施したドロップシャドウとは異なるパターンのドロップシャドウを作成し、チャートに設定します。

 べベルは、3Dのように立体的にしたり額縁のようにくぼんだ形状にする視覚効果です。べベルの高さによって、隆起したりくぼんだように見えます。

 アウトグロウは、輪郭の周りに光彩を設定する視覚効果です。蛍光灯の周りのぼけた光のような効果を設定します。光彩の色や範囲をプロパティで設定できます。

 それぞれの視覚効果は、DropShadowBitmapEffect、BevelBitmapEffect、OuterGlowBitmapEffectのタグで作成します。

<DropShadowBitmapEffect Color="DarkGray" Direction="-45" ShadowDepth="3" Softness="0.5" Opacity="0.5" />
<BevelBitmapEffect x:Name="animeBevelEffect" BevelWidth="1" EdgeProfile="CurvedIn" LightAngle="120" 
				  		   					 Relief="0.2" Smoothness="0.4" />
<OuterGlowBitmapEffect GlowColor="BlueViolet" GlowSize="30" Noise="2" Opacity="0.4" />

複数の視覚効果を設定する

 <c1chart:C1Chart>タグの中に<c1chart:C1Chart.BitmapEffect>タグを作成し、その中に設定を記述します。

 ただし、単体のタグはこの場所に記述しますが、複数の視覚効果を設定する場合は<BitmapEffectGroup>を作成し、その中に記述します。

Window1.xamlの追加コード
<c1chart:C1Chart Margin="37,67,73.5,87" Name="c1Chart1" Background="Transparent" Palette="Metro">

    <c1chart:C1Chart.BitmapEffect>
	    <BitmapEffectGroup>
        	<DropShadowBitmapEffect Color="DarkGray" Direction="-45" ShadowDepth="3" Softness="0.5" Opacity="0.5" />
            <BevelBitmapEffect x:Name="animeBevelEffect" BevelWidth="1" EdgeProfile="CurvedIn" LightAngle="120" 
                                         Relief="0.2" Smoothness="0.4" />
            <OuterGlowBitmapEffect GlowColor="BlueViolet" GlowSize="30" Noise="2" Opacity="0.4" />
        </BitmapEffectGroup>
    </c1chart:C1Chart.BitmapEffect>
複数の視覚効果を設定する
複数の視覚効果を設定する

視覚効果をアニメーションで設定する

 今度は、BevelBitmapEffectの光の当たり方をアニメーションさせます。作成したBevelBitmapEffectタグでは、LightAngleプロパティを120度に設定しています。これを、360度から0度まで回転させてべベルの形状が変化するようにアニメーションさせます。

アニメーションを実行するタイミングは、チャートにマウスポインタが重なった時のイベント「MouseEnter」を利用します。

 まず、<c1chart:C1Chart>タグの中に<c1chart:C1Chart.Triggers>タグを作成します。そして、アニメーションを動作させるイベント名と動作内容を設定します。

 個々のタグの内容の説明は省略しますが、光源の角度を360度から0度まで1秒間移動させるように設定します。AutoReverseプロパティをTrueに設定し、このライトの移動を時計回りと反時計回りの2回実行させます。

Window1.xamlの追加コード
<c1chart:C1Chart.Triggers>
	<EventTrigger RoutedEvent="c1chart:C1Chart.MouseEnter">
    	<BeginStoryboard>
        	<Storyboard>
            	 <DoubleAnimation
                	 Storyboard.TargetName="animeBevelEffect"
                     Storyboard.TargetProperty="LightAngle"
                     From="360" To="0" Duration="0:0:1" AutoReverse="True"
                 />
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</c1chart:C1Chart.Triggers>

チャートを画像で保存する

 C1Chartコンポーネントは、作成したチャートを画像データとして保存できます。この機能は、.NET FrameworkクラスライブラリのRenderTargetBitmapクラスを使用してビジュアルオブジェクトをビットマップに変換し、ファイルに保存します。

 この処理はxamlのコードではなく、Visual BasicまたはC#のイベントハンドラで処理を実行します。

ボタンの作成

 まずは、ページにボタンを配置します。ボタンにはBevelBitmapEffectを設定し、ページの右上に配置します。

Window1.xamlの追加コード
    <Button Height="27" HorizontalAlignment="Right" Margin="0,12,35,0" Name="Button1" 
            VerticalAlignment="Top" Width="114" Background="Coral">
        保存
        <Button.BitmapEffect>
            <BevelBitmapEffect BevelWidth="3" EdgeProfile="CurvedIn" LightAngle="320" Relief="0.4" 
                               Smoothness="0.4" />
        </Button.BitmapEffect>
   </Button>
</Grid>

イベントハンドラの処理

 配置したボタンをダブルクリックすると、Clickイベントハンドラが作成されるので、ここで画像への保存処理を作成します。

 まず、画像を保存するRenderTargetBitmapオブジェクトを作成します。コンストラクタの引数には、保存する画像サイズと解像度、保存フォーマットを指定します。フォーマットは、PixelFormatsクラスのメンバで指定しますが、Defaultを指定すると、適正なフォーマットを自動で設定してくれます。

 そして、RenderTargetBitmapクラスのRenderメソッドを実行します。このメソッドがVisualクラスのオブジェクトをレンダリングします。Visualクラスとは、WPFのUIクラスの派生元クラスで、C1Chartコンポーネントもこのクラスから派生しているので、Renderメソッドを使ってチャートを画像に保存できます。Renderメソッドの引数は1つで、ビットマップ化したいVisualオブジェクトを指定します。

 作成したビットマップは、FileStreamクラスを使ってファイルに保存します。

Visual Basic
Imports C1.WPF.C1Chart
Imports System.IO

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Dim bmp As New RenderTargetBitmap(600, 600, 96, 96, PixelFormats.Default)
        bmp.Render(C1Chart1)

        Dim bm_enc As New PngBitmapEncoder()
        Dim fname As New FileStream("chart.png", FileMode.Create)


        bm_enc.Frames.Add(BitmapFrame.Create(bmp))
        bm_enc.Save(fname)
        fname.Close()
        
        MessageBox.Show("保存しました。", "チャートの保存", MessageBoxButton.OK, MessageBoxImage.Information)
    End Sub
C#
using C1.WPF.C1Chart;
using System.IO;

private void Button1_Click(object sender, RoutedEventArgs e)
{
    RenderTargetBitmap bmp = new RenderTargetBitmap(600, 600, 96, 96, PixelFormats.Default);
    bmp.Render(c1Chart1);

    PngBitmapEncoder bm_enc = new PngBitmapEncoder();
    FileStream fname = new FileStream("chart.png", FileMode.Create);

    bm_enc.Frames.Add(BitmapFrame.Create(bmp));
    bm_enc.Save(fname);
    fname.Close();

    MessageBox.Show("保存しました。", "チャートの保存", MessageBoxButton.OK, MessageBoxImage.Information);
}
Windows1.xamlコード全文
<Window x:Class="wpfchart_cs.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="567" Width="714" xmlns:c1chart="http://schemas.componentone.com/xaml/c1chart">

    <Window.Resources>
        <DropShadowBitmapEffect x:Key="shadow" Color="Black" Direction="-45" ShadowDepth="3" Softness="0.5"  Opacity="0.5"/>
    </Window.Resources>
    
    <Grid Height="504" Width="646" Background="Beige">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="210*" />
            <ColumnDefinition Width="453*" />
        </Grid.ColumnDefinitions>
        <Border Style="{StaticResource chart_border}" Margin="12,12,0,0" Height="41" HorizontalAlignment="Left" VerticalAlignment="Top" Width="271" Grid.ColumnSpan="2">
            <TextBlock FontSize="20
                       " BitmapEffect="{StaticResource shadow}" Height="25" Width="189"> 売り上げグラフ
            </TextBlock>
        </Border>

        <Border Style="{StaticResource chart_border2}" Margin="12,67,32,12" Grid.ColumnSpan="2">
        <c1chart:C1Chart Margin="37,67,73.5,87" Name="c1Chart1" Background="Transparent" Palette="Metro" Height="238" Width="405">

            <c1chart:C1Chart.BitmapEffect>
                    <BitmapEffectGroup>
                        <DropShadowBitmapEffect Color="DarkGray" Direction="-45" ShadowDepth="3" Softness="0.5" Opacity="0.5" />
                        <BevelBitmapEffect x:Name="animeBevelEffect" BevelWidth="1" EdgeProfile="CurvedIn" LightAngle="120" 
                                           Relief="0.2" Smoothness="0.4" />
                        <OuterGlowBitmapEffect GlowColor="BlueViolet" GlowSize="30" Noise="2" Opacity="0.4" />
                    </BitmapEffectGroup>
                </c1chart:C1Chart.BitmapEffect>

                <c1chart:C1Chart.Triggers>
                    <EventTrigger RoutedEvent="c1chart:C1Chart.MouseEnter">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                   Storyboard.TargetName="animeBevelEffect"
                                   Storyboard.TargetProperty="LightAngle"
                                   From="360" To="0" Duration="0:0:1" AutoReverse="True"
                                   />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </c1chart:C1Chart.Triggers>
            
                <c1chart:C1Chart.Actions>
                <c1chart:ScaleAction Modifiers="" MouseButton="Left" />
                <c1chart:Rotate3DAction Modifiers="" MouseButton="Left" />
            </c1chart:C1Chart.Actions>
            <c1chart:C1Chart.Data>
                <c1chart:ChartData>
                    <c1chart:ChartData.ItemNames>2001 2002 2003 2004 2005 2006 2007 2008</c1chart:ChartData.ItemNames>
                    <c1chart:DataSeries Label="営業収入" Values="266001 274889 275863 274312 272334 268632 262338 252918" 
                                            SymbolFill="CadetBlue" />
                    <c1chart:DataSeries Label="営業費用" Values="262987 262358 269332 268585 266547 265939 264409 264423" 
                                            SymbolFill="Crimson" />
                </c1chart:ChartData>
            </c1chart:C1Chart.Data>
            <c1chart:C1ChartLegend DockPanel.Dock="Top" Height="48" Width="84" />
        </c1chart:C1Chart>
        </Border>

          
        <CheckBox Height="16.52" HorizontalAlignment="Left" Margin="107,28.48,0,0" Name="CheckBox1" 
                  VerticalAlignment="Top" Width="40" 
                  Checked="Checked" Unchecked="Unchecked" Grid.Column="1">3D</CheckBox>

        <Button Height="27" HorizontalAlignment="Right" Margin="0,20,50,0" Name="Button1" 
                VerticalAlignment="Top" Width="114" Background="Coral" Grid.Column="1" Click="Button1_Click">
            保存
            <Button.BitmapEffect>
                <BevelBitmapEffect BevelWidth="3" EdgeProfile="CurvedIn" LightAngle="320" Relief="0.4" 
                                   Smoothness="0.4" />
            </Button.BitmapEffect>
        </Button>
    </Grid>
</Window>

まとめ

 C1Chartコンポーネントは、WPF対応コンポーネントとして、WPFの機能を最大限生かしたチャート作成を実現するコンポーネントです。使いこなすには、WPFの知識が必要になりますが、視覚効果やアニメーションなどの優れた表現能力を使うことができます。

参考文献

製品情報

修正履歴

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/4537 2009/11/18 19:58

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング