プログラミング演習Ⅲ(2023)

【WPF練習13】図形描画と定期処理(5/7)

プロジェクトタイプC# WPFアプリケーション※
プロジェクト名T10a
ソリューション名PET10
ターゲットフレームワーク.NET 6.0 (長期的なサポート)

※ 「WPFアプリ(.NET Framework)」ではないので注意せよ!

注意
  • 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
    • 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
    • プロジェクトの作成作業については準備を参照せよ.

13-5. 図形の動的な追加/削除

Canvasへの図形の追加や削除はC#のコード上でも可能である.このためには_に示すように記述すればよい.

コード内でCanvasに部品を追加/削除する方法
// 部品の追加
Canvas型の変数.Children.Add(追加するなんらかの部品);

// 部品の削除
Canvas型の変数.Children.Remove(削除するなんらかの部品);

ではウィンドウにボタンを追加してイベントハンドラ上で動的に部品を追加することを試みてみよう. まずボタンを配置するために画面のレイアウトを_に示すように変更しよう. ここではGridを配置しなおして,canvas1をグリッド内に配置している. MainWindow.xaml_に示すように変更する.

ウィンドウのレイアウト
MainWindow.xamlの追記内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<Window x:Class="T10a.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:T10a"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="600" Background="#F0F0F0">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        
        <Button x:Name="button1" Grid.Row="0" Grid.Column="0" Content="追加"></Button>
        <Button x:Name="button2" Grid.Row="0" Grid.Column="1" Content="削除"></Button>

        <Canvas x:Name="canvas1" Grid.Row="1" Grid.ColumnSpan="2"
                Background="White" Width="512" Height="512">
                
            <!-- (..中略..) -->
            
        </Canvas>
    </Grid>

</Window>

ではボタンのクリックによってキャンバス内に楕円を追加してみることにしよう.MainWindow.xamlを編集して, button1Clickイベントを設定し イベントハンドラに_に示す内容を追記しよう.

MainWindow.xaml.csの追記内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private int count = 0; // 追加を行った回数

private void button1_Click(object sender, RoutedEventArgs e)
{
    // 追加する部品を作成する.
    var newbie = new Ellipse() 
    {
        Fill = Brushes.Orange,  // オレンジ色で塗りつぶし
        Stroke = Brushes.Black, // 境界線は黒
        Width = 64,             // 幅は64
        Height = 64,            // 高さも64
    };

    // 固定位置への追加だと分かりにくいので
    // 追加するつど配置位置をずらしている.
    Canvas.SetLeft(newbie, count * 40);
    Canvas.SetTop(newbie, count * 40);

    ++count;

    // ↑で作った部品をキャンバスに追加する.
    canvas1.Children.Add(newbie);
}

ここまで書けたら起動して「追加」ボタンを何度かクリックしてみよう. _に示すようにボタンを押すつど,オレンジ色の円が追加されることが分かるはずである.

作業結果

つぎにボタンのクリックによってキャンバス内に部品を削除することを試みよう.MainWindow.xamlで, button2Clickイベントを設定して イベントハンドラに_に示す内容を追記しよう.

MainWindow.xaml.csの追記内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private void button2_Click(object sender, RoutedEventArgs e)
{
    // キャンバスが空になってしまったら何もしない
    if (canvas1.Children.Count == 0) return;

    // 最後に追加された部品を取り出す.
    var target = canvas1.Children[canvas1.Children.Count - 1];

    // ↑で取り出した部品を削除する.
    canvas1.Children.Remove(target);
}

Canvas.Childrenプロパティは,そのパネルに配置されている部品のリストである. GridStackPanelでも同様にして動的に部品を追加,削除することが可能である.

ここまで書けたら起動して 「追加」ボタンをクリックしていくつか部品を追加してから , 「削除」ボタンをクリックしてみよう._に示すようにボタンを押すつど, 部品が削除されていくことが分かるはずである.

作業結果

ちなみに言うまでもないことだが Canvasに配置できる部品は図形部品だけではないCanvas内にはボタンやラベルといった部品も配置することが可能である. 試しにcanvas1にラベルを追加してみよう.MainWindow.xaml_に示す内容を追記する.

MainWindow.xamlの追記内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<Window x:Class="T10a.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:T10a"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="600" Background="#F0F0F0">
    <Grid>
    
        <!-- (..中略..) -->

        <Canvas x:Name="canvas1" Grid.Row="1" Grid.ColumnSpan="2"
                Background="White" Width="512" Height="512">
                
            <!-- (..中略..) -->
            
            <!-- ラベル(名前:label1) -->
            <Label x:Name="label1" Canvas.Left="125" Canvas.Top="200"
                   Content="わはは!"
                   Background="Black" Foreground="White"
                   FontSize="72"></Label>            
            
        </Canvas>
    </Grid>

</Window>

ここまで書けたらデザイナを表示するかアプリを起動して表示内容を確認してみよう. _に示すようにCanavs内に文言が表示されていることが分かるだろう.

作業結果

またこういったGUI部品も動的に追加することが可能である.button1のイベントハンドラを _のように変更する.

MainWindow.xaml.csの追記内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
private void button1_Click(object sender, RoutedEventArgs e)
{
    // 追加する部品を作成する.
    var newbie = new Button()       //
    {                               //
        Content = $"ボタン{count}", // 作成する部品をEllipseから
        Width = 100,                // Buttonに変更する.
        Height = 30,                //
    };                              //

    // 位置固定だと分かりにくいので追加する都度
    // 配置位置をずらしている.
    Canvas.SetLeft(newbie, count * 40);
    Canvas.SetTop(newbie, count * 40);

    ++count;

    // ↑で作った部品をキャンバスに追加する.
    canvas1.Children.Add(newbie);
}

ここまで書けたら起動して「追加」ボタンをクリックしてみよう. _に示すようにボタンを押すつど,ボタンが追加されていくことが分かるはずである.

作業結果

ちなみに ボタンを何度もクリックするとそのうち部品がキャンバスからはみ出すことが分かるだろう . はみ出した部品を表示しないようにするためにはCanvas.ClipToBoundsプロパティを設定すればよい. MainWindow.xaml_に示す内容を追記しよう.

MainWindow.xamlの追記内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<Window x:Class="T10a.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:T10a"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="600" Background="#F0F0F0">
    <Grid>
    
        <!-- (..中略..) -->
        
        <Canvas x:Name="canvas1" Grid.Row="1" Grid.ColumnSpan="2"
                Background="White" Width="512" Height="512"
                ClipToBounds="True"> <!-- ← キャンバスからはみ出した部品は非表示にする -->
                
            <!-- (..中略..) -->                  
            
        </Canvas>
    </Grid>

</Window>

ここまで書けたら起動して「追加」ボタンを何度もクリックしてみよう. _に示すようにはみ出した部品は見切れた状態で表示されることが分かるだろう.

作業結果
Last updated on 2024-01-09
Published on 2024-01-09

Powered by Hugo. Theme by TechDoc. Designed by Thingsym.