0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🟧 第5回:【マーカー描画編】分割区間をオーバーレイで可視化する

Posted at

はじめに:操作の手応えは「目に見えること」から始まる

このツールは「動画から特定区間だけを抽出して出力する」ためのものであり、当然ながらユーザーは「どこからどこまで」を視認して操作したくなります。

再生してから「この辺りだな」と目で追い、区間を指定。すると、シークバー上にその範囲が色で反映される。
この仕組みが、このツールに“わかりやすさ”を加えてくれました。

この回では、マーカー描画機能の実装方法と生成AIとのやりとりを詳しく見ていきましょう。


マーカーとは?:シークバー上に描かれる区間インジケーター

このツールには、動画の再生位置を表すシークバー(TrackBar)があります。
その上にオーバーレイとして描画される“マーカー”が以下の3パターンに対応しています:

  • 🟧 開始+終了時間あり → 指定区間全体を塗りつぶし(橙色)
  • 🟧 開始時間のみ → 開始位置に縦線(橙色)
  • 🟧 終了時間のみ → 終了位置に縦線(橙色)

(現在のversionでは要件変更によりこちらを変更しております。)

こうした描画は、DataGridView 上のジョブに登録された時間情報をもとに生成されています。


Copilotに指示した内容

私は生成AIに次のような指示を出しました:

💬「再生位置のバーに、開始/終了時間をマーカーとして描画したい」
💬「開始だけなら線、開始+終了なら矩形塗りつぶしで」
💬「C# 7.3なので using var は使わず、using ブロックで書いて」

Copilotは完璧に意図をくみ取り、以下のような描画コードを生成してくれました。


MarkerOverlay_Paint() の実装例(C# 7.3対応)

private void MarkerOverlay_Paint(object sender, PaintEventArgs e)
{
    if (_mediaPlayer == null || _mediaPlayer.Length <= 0) return;

    double totalSeconds = _mediaPlayer.Length / 1000.0;
    int width = markerOverlay.Width;

    foreach (DataGridViewRow row in dgvJobs.Rows)
    {
        if (row.IsNewRow) continue;

        bool hasStart = TimeSpan.TryParse(row.Cells[0]?.Value?.ToString(), out TimeSpan start);
        bool hasEnd = TimeSpan.TryParse(row.Cells[1]?.Value?.ToString(), out TimeSpan end);

        int x1 = hasStart ? (int)(start.TotalSeconds / totalSeconds * width) : -1;
        int x2 = hasEnd   ? (int)(end.TotalSeconds / totalSeconds * width) : -1;

        if (hasStart && hasEnd && end > start)
        {
            using (Brush fill = new SolidBrush(Color.FromArgb(100, Color.Orange)))
            {
                e.Graphics.FillRectangle(fill, x1, 0, x2 - x1, markerOverlay.Height);
            }
        }
        else if (hasStart)
        {
            using (Pen pen = new Pen(Color.Orange, 3))
            {
                e.Graphics.DrawLine(pen, x1, 0, x1, markerOverlay.Height);
            }
        }
        else if (hasEnd)
        {
            using (Pen pen = new Pen(Color.Orange, 3))
            {
                e.Graphics.DrawLine(pen, x2, 0, x2, markerOverlay.Height);
            }
        }
    }
}

💡 TimeSpan.Parse は万が一無効な文字列だった場合に備え、TryParse にしています。

💡 markerOverlayTrackBar と同じ座標・サイズで配置された Panel であり、Paint イベントによりマーカーが描かれます。


視覚的なメリット

  • 🟠 分割ジョブが「どこに設定されたか」をすぐに確認できる
  • 🟠 開始時間だけ設定 → 縦線で位置が即座にわかる
  • 🟠 完全な区間(開始+終了) → 濃淡つき矩形で明確に視認可能
  • 🟠 再生バーとの重なりで、現在位置との比較ができる

Copilotがくれたアドバイスの一つに:

「同じオーバーレイパネル上で Invalidate() を使えば、スクロールや再生位置の更新時に自動で再描画できますよ」

というものがありました。
実際に、UpdateSlider()Scroll イベントで markerOverlay.Invalidate() を呼び出すことで常に更新され続けるようになりました。


スライダー移動時の連動描画(補足)

private void Slider_Scroll(object sender, EventArgs e)
{
    _mediaPlayer.Time = slider.Value * 1000;
    markerOverlay.Invalidate();
}

上記の処理で、スライダーを動かすたびに描画が更新され、マーカー位置と再生位置が同期して見えるようになっています。


描画の拡張案(次回以降も可能)

以下のような発展的機能も、Copilotなら対応してくれそうです:

  • 再生位置そのものもマーカーとして描画する(赤線など)
  • 現在選択しているジョブを強調表示(太線など)
  • ジョブ行のインデックスに応じて色分け
  • シークバーの上にラベル(時刻)を表示

Copilotに「マーカーを太くしてラベルを追加して」と伝えれば、すぐにコードを返してくれます。


まとめ:見える化の力とAIの柔軟さ

この回の学びは、機能の視覚化による操作性向上と、それを支える生成AIの柔軟性です。

機能 実現手段 学び
区間マーカー描画 Paint イベント+DataGridView 指定区間の視認性向上
再描画制御 Invalidate() 呼び出し 再生中/スクロール時でも更新可能
C# 7.3 対応 using (...) {} 構文 Copilotは言語バージョンに応じて調整可能
プロンプトから生成 Copilotとの対話 「こうしたい」がすぐ形になる

マーカー描画は、分割ツールとしての信頼性を視覚的に高めてくれる要素です。
生成AIがそれを忠実に構築してくれたおかげで、私はC#初心者でも安心してUIの精度向上に集中できました。


次回第6回【ジョブ管理編】

いよいよ分割処理の要となる、「ジョブの登録/編集/削除」機能の詳細に入っていきます。

  • 開始時間/終了時間/ファイル名の構成
  • 自動的に新しい行に移る設定
  • 削除ボタンとイベント処理の組み方
  • 一括出力に向けた準備ステップ
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?