こんにちは、ENGかぴです。
VB.NET(Visual Basic 2022)のデスクトップアプリでタイマーの実装とイベントの追加方法をまとめました。タイマーを使用してストップウォッチを作成して動作確認しています。またタイマーの誤差が大きくなってしまう事例を紹介しています。
以下はVisual Basic 2022をVB2022とします。
VB.NET(VB2022)のデスクトップアプリで動作確認したことを下記リンクにまとめています。
VB.NET(VB2022)のデスクトップアプリ開発でできること
フォームにタイマーを実装する
スタートメニューからVisual Studio 2022を起動し、VB2022のプロジェクトを作成します。初期配置されているフォームにボタンを実装しイベントを追加します。
毎回スタートメニューから開くのが面倒な場合はタスクバーにピン止めもしくはスタートメニューのVisual Studio 2022を左クリックで選択した状態でデスクトップにリンクコピーしても良いと思います。
広告
PR:わからないを放置せず、あなたにあったスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!
タイマーを使って作成するアプリ
本記事では「開始」ボタンを押すとタイマーをスタートし1秒毎に経過時間を表示するアプリを作成します。
ボタンの色が薄い緑(LightGreen)の場合は使用可能の状態表示とし、薄い青(LightBlue)の場合は使用禁止の状態表示とします。
プロジェクトの作成
Visual Studio 2022を開き「新しいプロジェクトの作成(N)」を選択します。
新しいプロジェクトの作成画面に遷移するのでVisual Basicを選択し、候補を絞るためにプラットフォームにWindows、プロジェクトの種類にデスクトップを選択します。候補の中から「Windowsフォームアプリ」選択して「次へ(N)」をクリックします。「Windowsフォームアプリ」をダブルクリックしても次に進みます。
プロジェクト名や保管場所を指定します。例ではプロジェクト名をtimerにしています。場所(L)はデフォルトから変更して、Cドライブ上に作成したWorkSpaceのvb2022フォルダを指定しています。
ソリューション名(M)は「ソリューションとプロジェクトを同じディレクトリに配置する(D)」のチェックを外すと指定することができます。チェックを入れた場合はtimerフォルダ内にslnファイルなどのファイルが配置されます。
「次へ(N)」をクリックすると追加情報に遷移します。
フレームワークはデフォルトで「.NET6.0(長期的なサポート)」になっています。そのまま使用しても問題ありませんが、例では「.NET7.0(標準用語のサポート)」を選択しています。「作成(C)」をクリックするとエディター画面に遷移します。エディター画面でツールボックスが表示されていない場合はツールボックスを追加します。
エディター上部の表示(V)を選択し一覧からツールボックス(X)を選択してクリックするとツールボックスの表示が追加されます。
タイマー(Timer)の実装
初期で配置されているForm1.vb[デザイン]にタイマー(Timer)を追加します。ツールボックスのコンポーネントタブからTimerを選択します。(すべてのWindowsフォームからも選択できます。)Form1を任意の名称に変更している場合はForm1を変更した名前に置き換えて下さい。
Timerを選択した状態でフォーム内を左クリックするとフォームの下の個所にTimer1が配置されます。Timer1を選択するとプロパティが表示されます。Timer1をダブルクリックするとTimer1_Tick()関数が生成されます。Timerのプロパティは以下の通りです。
項目 | 説明 |
---|---|
Enabled | コントロールの操作の許可と禁止を指定します。 例)True: 許可、False: 禁止 |
Interval | タイマー動作のインターバル(間隔ms単位)を指定します。 例)100 |
Enabledは初期の状態でFalseとなっているため初期動作からタイマーを起動する場合はTrueを指定する必要があります。
ボタン(Button)の実装
ボタンの実装とイベントの追加の方法を下記記事にまとめています。ボタンの構成は下記記事のButton1~Button3の構成を流用して使用します。
VB.net(VB2022)のボタンの実装とイベントの追加方法
開始ボタンを押すとタイマーを動作開始し、停止ボタンを押すとタイマーの更新をストップします。クリアボタンを押すと経過時間のカウント値をクリアします。
Label1とLabal2もコモンコントロール(すべてのWindowsフォーム)から追加します。Labelは文字の表示に使用します。
広告
マイベスト3年連続1位を獲得した実績を持つ実践型のプログラミングスクール
変数の宣言
アプリで共通する変数を宣言する場合はフォームクラス内で変数を宣言する必要があります。VBの場合はDimでメモリに変数を割り当てます。
Public Class Form1
Dim count As UInt32'全体で有効
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim sec As UInt16'サブルーチン内で有効
End Sub
End Class
例ではアプリ全体で使用できる変数としてcountを符号なしの32ビットで宣言しています。クラス内で宣言した場合はアプリを終了しない限りメモリを割り当てた状態になります。
サブルーチンのTimer1_Tick()内で宣言したsecはサブルーチンの処理では値を保持できますが、サブルーチンを抜けるとメモリを開放するため値を保持することができません。
宣言の仕方を用途によって使い分けることでメモリの割り当てが最小限になりメモリ負荷が少ない構成になります。
イベントの追加
Button1などのコントロールに対してイベントの追加を行う必要があります。エディターを選択している状態でF7を押すか右1クリックで表示されるメニュー「コードの表示(C)」を選択するとコードの編集画面(Form1.vb)に遷移します。次のイベントを追加します。
- フォームを呼び出したときに一度だけ処理するLoadイベント
- Timer1がインターバルの間隔で呼び出された時に処理するTickイベント
- Button1をクリックしたときに呼び出すClickイベント
- Button2をクリックしたときに呼び出すClickイベント
- Button3をクリックしたときに呼び出すClickイベント
1~5のイベントは、クリックとダブルクリックで追加することができます。フォームのLoadイベントはForm1[デザイン]をダブルクリックすると追加されます。ButtonのClickイベントはButton1~Button3をダブルクリックするとがイベントが追加されます。
Loadイベント、Clickイベント以外を追加する場合もあるため、以下ではコードエディターでイベントを追加する方法を説明します。
①コントロールの選択を行います。イベントを追加するコントロールを選択し、イベント一覧から追加するイベント追加します。例ではForm1のイベントとして②Loadイベントを追加しています。同様にしてButton1~Button3はClickイベントを追加します。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
End Sub
イベントを選択するとコードが自動で生成されます。自動再生されたサブルーチンの後方にHandles Button1.Clickのように記述されている部分がイベントの発生要因になります。生成したサブルーチンに処理を追加します。
フォームを読み込んだ時に初期化
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Button1.Text = "開始"
Button2.Text = "停止"
Button3.Text = "クリア"
GroupBox1.Text = "操作盤"
Timer1.Enabled = False 'Timer1のプロパティを変更
Timer1.Interval = 1000
Label1.Text = "カウント数:0"
Label2.Text = "経過時間:00:00:00"
End Sub
Form1_Load()関数はForm1が読み込まれた時に一度だけイベントが発生します。アプリの初期化が必要な場合はForm1_Load()関数に処理を追加します。
Button1~Button3及びGroupBox1のText文字を指定しています。Timer1のEnabledとIntervalを指定していますが、プロパティに直接指定しても同じ動作になります。プロパティの項目をコードで指定すると後着が優先となるのでコードが上書きします。
Label1とLabel2は初期状態で表示する文字列をTextに指定しています。
Timer1のインターバル処理
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim sec As UInt16 '秒
Dim min As UInt16 '分
Dim hou As UInt16 '自
Dim str As String '文字列を生成
count += 1
sec = count Mod 60
min = Math.Floor(count / 60) Mod 60
hou = Math.Floor(count / 3600)
str = hou.ToString("00")
str &= ":"
str &= min.ToString("00")
str &= ":"
str &= sec.ToString("00")
Label1.Text = "カウント数:" & count
Label2.Text = "経過時間:" & str
End Sub
Timer1のEnabledをTrueにするとインターバル毎にTimer_Tick()関数がコールされます。開始からのカウントを1秒毎に更新しながらカウントと経過時刻をLabel1、Label2に表示します。
経過時刻はカウントを時、分、秒で換算して表示します。秒は0~59を表示するためカウントを60で割った余りになります。Modメソッドを使用すると余りを計算することができます。A Mod B はAをBで割った余りを計算します。
分はカウントを60で割った商を0~59で表示するためModメソッドで余りを計算します。カウントを60で割った商を計算する場合に小数点以下を切り捨てるためMathクラスのFloorメソッドを使用しています。
時はカウントを3600で割った商になりますが、小数点以下を切り捨てるためMathクラスのFloorメソッドを使用しています。
時、分、秒の時刻表示はString型の変数のstrで生成してLabelに指定します。文字列は “” で囲んで指定します。文字列の連結は & を使用します。
例ではstrの初期値に時の計算結果を指定します。時の計算結果を00のように2桁の文字で表示するためToString()メソッドで表示形式を指定しています。時以降は &= で文字列を連結して追加しています。
Label1.textはカウント数:の文字列に現在のカウントを連結して表示します。Labal2.Textは経過時刻:の文字列にstrを連結して表示します。
Button1をクリック
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.BackColor = Color.LightBlue
Button2.BackColor = Color.LightGreen
Timer1.Enabled = True
End Sub
Button1を押すと開始になるためBackColorにColorの型のLightBlueを指定し、使用禁止の状態表示にします。Button2は開始している状態では「停止」を待機します。使用可能の状態表示のため、BackColorにLightGreenを指定します。
開始でTimer1を開始するためTimer1のEnabledをTrueにします。
Button2をクリック
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Button1.BackColor = Color.LightGreen
Button2.BackColor = Color.LightBlue
Timer1.Enabled = False
End Sub
Button2を押すと「停止」状態になるためBackColorにLightBlueを指定し、使用禁止の状態表示にします。Button1は「開始」が押されるのを待機します。使用可能の状態表示のためBackColorにLightGreenを指定します。
停止でTimer1を停止するためTimer1のEnabledをFalseにします。
Button3をクリック
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
count = 0
Label1.Text = "カウント数:0"
Label2.Text = "経過時間:00:00:00"
End Sub
Button3はカウントとLabelの表示をクリアします。
インターバルが短いと誤差が大きくなる事例(参考)
タイマー(Timer)の実装でタイマーのインターバルを短くしすぎるとタスクの遅延などによってインタバールが正確に取れず誤差が大きくなることを説明しました。誤差が大きくなる事例について以下の条件で動作確認します。
Timer1のIntervalに10を指定し、Timer1_Tick()内のsec、min、houを以下のように変更します。
Timer1.Interval = 10 'Form1_Load内で変更
'計算式を以下に変更(10ms分解能)
sec = count Mod 100
min = Math.Floor(count / 100) Mod 60
hou = Math.Floor(Math.Floor(count / 100) / 60)
スマホのストップウォッチとFormのアプリを同時にスタートして1分間の経過時間を表示します。
スマホのストップウォッチが1分経過したときにの時刻を比較するとFormアプリの結果は38秒であり12秒誤差が出ていました。動作確認する環境にもよりますが目視でも1秒をカウントするペースが遅いことが分かります。
PR:わからないを放置せず、あなたにあった最低限のスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!
動作確認(デバッグ)
イベントのコードを追加した後はデバッグを行います。デバッグは実際のアプリケーションの動作を模擬して実行するものです。デバッグの開始はエディタ上部の「▶timer」(赤枠)をクリックすると開始します。
デバッグを開始するとForm1がアプリケーションとして表示されます。この表示はLoadイベントを処理した後、次のイベントの発生を待機している状態です。「開始」を押すとタイマーがスタートしカウント数を更新しながら経過時間の表示を行います。
カウント数が1秒毎に更新されることが確認できました。スマホのストップウォッチと同時にスタートして1分間の動作確認を行ったところ目立った誤差がないことも確認できました。
「停止(Button2)」を押すとタイマーが停止し、カウント数及び経過時間の表示の更新が停止することが確認できました。また、「クリア(Button3)」を押すとカウント数及び経過時間の表示がクリアされることが確認できました。
コードのデバッグを行う場合は、コードエディタでブレークポイントを置くことで一時的にプログラムを停止させることができます。
ブレークポイントはコードエディターの最左部分をクリックして●マークが表示されれば設置できています。例ではButton3がクリックされた時に発生したイベントの先頭部分にブレークポイントを置いています。この状態でButton3をクリックするとブレークポイントでプログラムが一時停止します。
F11を押すとステップ実行になるため1行ずつ内容を確認しながらデバッグを行うことができます。上部の「▶続行(C)」をクリックするとブレークポイント状態から通常の動作に復帰します。
関連リンク
VB.NET(VB2022)のデスクトップアプリで動作確認したことを下記リンクにまとめています。
VB.NET(VB2022)のデスクトップアプリ開発でできること
マイクロソフトはVisual Studio以外にもVSCodeという便利なエディターを提供しています。下記リンクではVSCodeのインストールの仕方からC言語開発環境の作り方までをまとめています。
PR:(即戦力のスキルを身に着ける:DMM WEBCAMP 学習コース(はじめてのプログラミングコース))
最後まで、読んでいただきありがとうございました。