WPFのボタンで再生・一時停止・停止を切り替えるステートマシンを実装してみる

コンピュータ

ソースコード

ファイル名:StateMachineSample.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net10.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

ファイル名:MainWindow.xaml.cs

using System.Windows;

namespace StateMachineSample;

public partial class MainWindow : Window
{
    readonly PlayerStateMachine _machine = new();

    public MainWindow()
    {
        InitializeComponent();

        PlayPauseButton.Click += PlayPause_Click;
        StopButton.Click += Stop_Click;

        _machine.StateChanged += OnStateChanged;
        UpdateUI();
    }

    void PlayPause_Click(object sender, RoutedEventArgs e)
    {
        _machine.TogglePlayPause();
    }

    void Stop_Click(object sender, RoutedEventArgs e)
    {
        _machine.Stop();
    }

    void OnStateChanged(PlayerState state)
    {
        UpdateUI();
    }

    void UpdateUI()
    {
        StateText.Text = $"状態: {_machine.State}";

        // ▶ / ⏸ 表示切り替え
        PlayPauseButton.Content =
            _machine.State == PlayerState.Playing
                ? "⏸ 一時停止"
                : "▶ 再生";
        
        // ▼ 排他制御
        switch (_machine.State)
        {
            case PlayerState.Stopped:
                PlayPauseButton.IsEnabled = true;
                StopButton.IsEnabled = false;
                break;

            case PlayerState.Playing:
            case PlayerState.Paused:
                PlayPauseButton.IsEnabled = true;
                StopButton.IsEnabled = true;
                break;
        }
    }
}

ファイル名:PlayerStateMachine.cs

public enum PlayerState
{
    Stopped,
    Playing,
    Paused
}

public class PlayerStateMachine
{
    public PlayerState State { get; private set; } = PlayerState.Stopped;

    public event Action<PlayerState>? StateChanged;

    void SetState(PlayerState state)
    {
        State = state;
        StateChanged?.Invoke(State);
    }

    // ▶ 再生 / 一時停止 ボタン
    public void TogglePlayPause()
    {
        switch (State)
        {
            case PlayerState.Stopped:
                SetState(PlayerState.Playing);
                break;

            case PlayerState.Playing:
                SetState(PlayerState.Paused);
                break;

            case PlayerState.Paused:
                SetState(PlayerState.Playing);
                break;
        }
    }

    // ■ 停止ボタン
    public void Stop()
    {
        if (State != PlayerState.Stopped)
            SetState(PlayerState.Stopped);
    }
}

ファイル名:MainWindow.xaml

<Window x:Class="StateMachineSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="StateMachine Sample"
        Width="300"
        Height="160">

    <StackPanel Margin="20" VerticalAlignment="Center">

        <StackPanel Orientation="Horizontal"
                    HorizontalAlignment="Center"
                    Margin="0,0,0,15">

            <Button x:Name="PlayPauseButton"
                    Width="120"
                    Margin="5"/>

            <Button x:Name="StopButton"
                    Content="■ 停止"
                    Width="80"
                    Margin="5"/>
        </StackPanel>

        <TextBlock x:Name="StateText"
                   FontSize="16"
                   HorizontalAlignment="Center"/>
    </StackPanel>
</Window>

実行例

  • 停止状態
  • 再生
  • 一時停止

コメント