はじめに
#2で(下記)、設定画面を実装した続きから行う。(全3記事を予定)
プロジェクトの作成(#2の続きから)
#タイマー画面の実装
そもそも、ポモドーロタイマー(テクニック)とは(下記URLより)
ポモドーロテクニックは、仕事を 25 分ずつのセッションに分け、そのあいだに短い休憩をはさんで行う時間管理術です。集中力を維持しながら生産性を上げる効果があるこの手法は、ビジネスシーンだけでなく、勉強などに集中したいときにも活用できるテクニックです。
まず、画面を作成する
<Grid>
<Ellipse Fill="#FF4CAF50" Width="300" Height="300" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="TimerTextBlock" FontSize="72" FontWeight="Bold" TextAlignment="Center" Foreground="White" Margin="0,0,0,20"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button x:Name="StartButton" Content="Start" Click="StartButton_Click" Margin="5" Style="{StaticResource AccentButtonStyle}" CornerRadius="10" Padding="15,5"/>
<Button x:Name="ResetButton" Content="Reset" Click="ResetButton_Click" Margin="5" Style="{StaticResource DefaultButtonStyle}" CornerRadius="10" Padding="15,5"/>
</StackPanel>
<TextBlock x:Name="StatusTextBlock" HorizontalAlignment="Center" Margin="0,20,0,0" Foreground="WhiteSmoke"/>
</StackPanel>
</Grid>
次に、タイマーのロジックを実装する
private DispatcherTimer timer;
private TimeSpan remainingTime;
private bool isRunning = false;
private int pomodoroCount = 0;
private int pomodoroPhase = 4;
private double pomodoroMinutes = 25;
public TimerPage()
{
this.InitializeComponent();
remainingTime = TimeSpan.FromMinutes(pomodoroMinutes);
UpdateTimerDisplay();
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += Timer_Tick;
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
if (!isRunning)
{
timer.Start();
isRunning = true;
StartButton.Content = "Pause";
}
else
{
timer.Stop();
isRunning = false;
StartButton.Content = "Start";
}
}
private void ResetButton_Click(object sender, RoutedEventArgs e)
{
timer.Stop();
isRunning = false;
StartButton.Content = "Start";
remainingTime = TimeSpan.FromMinutes(pomodoroMinutes);
pomodoroCount = 0;
UpdateTimerDisplay();
}
private void Timer_Tick(object sender, object e)
{
remainingTime = remainingTime.Subtract(TimeSpan.FromSeconds(1));
UpdateTimerDisplay();
if (remainingTime == TimeSpan.Zero)
{
timer.Stop();
isRunning = false;
StartButton.Content = "Start";
pomodoroCount++;
string message = (pomodoroCount % pomodoroPhase == 0) ? "Long break" : "Short break";
ShowNotification(message);
remainingTime = (pomodoroCount % pomodoroPhase == 0) ? TimeSpan.FromMinutes(20) : TimeSpan.FromMinutes(5);
UpdateTimerDisplay();
}
}
private void UpdateTimerDisplay()
{
TimerTextBlock.Text = remainingTime.ToString(@"mm\:ss");
if (isRunning)
{
StatusTextBlock.Text = $"Pomodoro {pomodoroCount + 1} / {pomodoroPhase} in progress";
}
else
{
if (pomodoroCount % pomodoroPhase == 0 && pomodoroCount > 0)
{
StatusTextBlock.Text = "Long break";
}
else if (pomodoroCount > 0)
{
StatusTextBlock.Text = "Short break";
}
else
{
StatusTextBlock.Text = "Waiting to Start";
}
}
}
private async void ShowNotification(string message)
{
ContentDialog dialog = new ContentDialog
{
Title = message,
CloseButtonText = "OK",
XamlRoot = this.Content.XamlRoot
};
await dialog.ShowAsync();
}
これだけだと寂しいので
タイマーのダイアログが起動している間、効果音を鳴らし続けるロジックも追加する
((著作権フリー)効果音が下記からDLいたしました。)
private async void ShowNotification(string message)
{
ContentDialog dialog = new ContentDialog
{
Title = message,
CloseButtonText = "OK",
XamlRoot = this.Content.XamlRoot
};
MediaPlayer player = new MediaPlayer();
StorageFolder installedLocation = Package.Current.InstalledLocation;
StorageFile file = await StorageFile.GetFileFromPathAsync(System.IO.Path.Combine(installedLocation.Path, "Assets\\alert.mp3"));
player.Source = MediaSource.CreateFromStorageFile(file);
player.IsLoopingEnabled = true;
player.Play();
await dialog.ShowAsync();
player.Pause();
player.Dispose();
}
これでタイマー画面の実装完成!
#Todoリスト画面の実装
画面を作成する
<StackPanel Orientation="Vertical" Margin="20">
<TextBox x:Name="NewTodoTextBox" PlaceholderText="New Todo" />
<Button x:Name="AddButton" Content="Add" Click="AddButton_Click" Margin="0,5,0,0" />
<ListView ItemsSource="{x:Bind todos}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{Binding}" VerticalAlignment="Center" />
<Button Margin="10,0,0,0" Content="Delete" Click="DeleteButton_Click" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
Todoリストでもサウンド設定と同じくローカルのストレージを利用して
Todoリストをメモ上に保存するロジックを実装する
private const string StorageFileName = "todos.txt";
private ObservableCollection<string> todos = new ObservableCollection<string>();
public TaskPage()
{
this.InitializeComponent();
Loaded += TaskPage_Loaded;
}
private async void TaskPage_Loaded(object sender, RoutedEventArgs e)
{
await LoadTodosAsync();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
private async Task LoadTodosAsync()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
try
{
StorageFile file = await localFolder.GetFileAsync(StorageFileName);
string content = await FileIO.ReadTextAsync(file);
string[] lines = content.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
todos.Clear();
foreach (string line in lines)
{
todos.Add(line);
}
}
catch (FileNotFoundException)
{
//NOT EXIST
StorageFile file = await localFolder.CreateFileAsync(StorageFileName, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, "");
}
}
private async Task SaveTodosAsync()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.CreateFileAsync(StorageFileName, CreationCollisionOption.ReplaceExisting);
string content = string.Join(Environment.NewLine, todos);
await FileIO.WriteTextAsync(file, content);
}
private async void AddButton_Click(object sender, RoutedEventArgs e)
{
string newTodo = NewTodoTextBox.Text.Trim();
if (!string.IsNullOrEmpty(newTodo))
{
todos.Add(newTodo);
NewTodoTextBox.Text = "";
await SaveTodosAsync();
}
}
private async void DeleteButton_Click(object sender, RoutedEventArgs e)
{
if (sender is Button button && button.DataContext is string todo)
{
todos.Remove(todo);
await SaveTodosAsync();
}
}
これでTodoリスト画面の実装完成!
これで全画面の実装が完了したのでアプリケーション完成!!!
#最後に
アプリケーションをデバッグ環境ではなく、リリースして使う方法を紹介する。
プロジェクトを右クリックでパッケージ化して公開するをクリック。
アプリ パッケージの作成を選択する。
サイドローディングを選択し次へ。
証明書を作成するを選択し、作成ボタンを押下する
自己署名の欄に発行者共通名と適当なパスワードを入れてOK押下
信頼するボタンを押下して次へ、
パッケージの選択と構成で任意の選択をして次へ、
更新設定も任意のパスをいれて作成する。
すると、成果物の出力先フォルダのパスが表示される
上記のパスにある成果物内のインストーラーをクリックするとリリース版がインストールされる。
今回の成果物
ソース
まとめ
全3記事でポモドーロタイマーのアプリケーションをWinUI3で実装してみた。
WinFormsと比べると情報が少なく、苦労する箇所もあったが、
Win 3 GalleryやMS公式のリファレンスを参照してどうにかなった👍
今後も学習していきたい。📝