この記事で扱っていること
- 操作の履歴を表示させる方法
を紹介しています。
注意:すべてのエラーを確認しているわけではないので、記事の内容を実装する際には自己責任でお願いします。また、エラー配線は適当な部分があるので適宜修正してください。
ユーザーがどのタイミングでどの操作をしたか、そしてその操作の結果はどうだったかなど、一連の操作の履歴を表示させることができるプログラムです。
とはいっても、本質的な部分はそのような表示を行わせるためのサブVI(機能的グローバル変数のような形で実装)を用意し、これに各操作に対して適切な文字を与えるだけです。
仕組みさえ理解してしまえば複数のプログラムで使いまわしできると思います。
どんな結果になるか
機能を紹介するために、簡単なステートマシンのプログラムを例にとります。
フロントパネルは以下の図のようにしており、ユーザーが操作するボタンが2つ、それぞれ押すと適当なテストが実行され、その結果と、適当な基準をパスしたかどうかの判定を表示します。
これらのボタン操作の履歴を表示する文字列表示器があり、表示のリセットや、一度に表示する履歴の行数の指定を行えます。
プログラムを実行するとまず実行した時間が表示され、その後各テストがいつ行われたか、結果が出たのはいつでどんな結果だったかを表示します。
プログラムの構造
まずは、今回の機能の肝となる、サブVIの中身を紹介します。大元のベースは、どこかのサンプルにあったプログラムを元にしていますが、表示する行の変更の機能を追加しています。
表示行数を指定する制御器のデフォルトは、後のプログラムの都合上、「あり得ない」数(指定しえない大きさの数でもいいですが、一番単純なのは負の数)としてデフォルト設定しておきます(デフォルト設定は右クリックで「データ操作」から行えます)。
単純に、外部(メインVI)から送られてきた文字列を、適当な形にフォーマットして、それらを配列のデータとしてため込みます(このため混む仕組みにシフトレジスタを使用します)。あとは指定された表示行数分だけ部分配列で抜き出して、配列から文字列にするために関数を使用しています。
メインVIから「表示行数」の数値制御器への配線がなかった場合には、このサブVIが実行される際に「表示行数」はデフォルト値が使用されますが、このデフォルト値が使用されているかどうかを判定することで、「表示行数だけ変える」という動作を実現するイベントを後で作ることができます。
また、メインVIの文字列表示器に文字を載せるため、サブVIでは「メインVIの文字列表示器のリファレンス」を取得する必要がありますが、このサブVIが呼び出されるたびにリファレンスを渡すのは面倒なので、一度渡されたものを使いまわせるようにしています。
文字列のフォーマットの仕方はお好みに合わせてください。この記事で紹介しているのは現在の時刻を取得関数で得たタイムスタンプを年月日含めて時刻情報として出せるようにフォーマットしていますが、こうした文字列をどのようにフォーマットするかは自由です。
こちらのサブVIを組み込んだ、上で紹介したステートマシンのプログラムの説明とともに、このサブVIの使い方を紹介します。本当はどんなプログラムでもこのサブVIを使用できますが、単純でいて応用範囲が広く、そこまでLabVIEWに慣れていない方でも扱いやすいのがステートマシンでの実装だと思います。
ステートマシンのプログラムはイベント駆動型にしており、各ボタンを押すとそれぞれのステートが実行されます。
まずは初期化のためのinitステートから始めます。ここでは、先ほどのサブVIに対してinitというブールにTRUEを入れ初期化し、メインVIの文字列表示器のリファレンスを渡しています。
以降は、履歴表示をリセットするイベント以外はリファレンスをサブVIに渡す必要はなくなります。
下記の図で配線している「5」は、表示行数の最初の設定です。ここで5と配線している時だけその数が適用され、以降のメインVIの中でサブVIが呼び出されても表示行数について配線をしなければ、「あり得ない」数がサブVI中で指定されることになります(サブVIのブロックダイアグラムで「あり得ない」数として-1を定数で指定し等しくない?のノードで判別することで、最初に指定した5が以降行数として使用されることになります)。
そのあとはもう一度このサブVIを呼び出し、表示させたい文字列だけを配線します。
この後、イベントを待機するeventステートに移ります。ここはお好みにカスタマイズできますが、表示行数の設定や、履歴のリセットボタンを押した際のイベントについては以下の図のように設定します。
表示行数の値変更イベントでは、initのブールボタンは配線せずに、表示行数だけ変えていることに注意してください。
あとは、各ステートで行いたい処理の最初と最後に今回のサブVIを置いて、それぞれどういう状況なのか、あるいはどういった結果となったかという情報を文字列で渡します。
例えば、ある処理(下の図ではtestAとしています)の結果を文字列にフォーマットし、これをサブVIに渡しています。実際にプログラムを組む場合には、この図のtestAにあたる部分を、自分のしたい処理に置き換える、というイメージになります。
testAのサブVIの中身は全く本質的な話ではないですが、一応載せておきます。
他の処理があった場合も全く同じです(以下の図ではtestBとして、testA以外の処理をするステートを載せています。testBの内容はtestAと同じにしているので省略します)。
最後は終了ボタンが押された場合に実行するfinishステートです。もし終了の時刻や終了したということを表示したいのであれば以下の図のようにしますが、特に終了したことを表示する必要がないのであればサブVIは必要ありません。
より多くの情報を表示する場合
今回のプログラムの例では、外部からの入力としては二つの情報(operationとoption)を入れていましたが、場合によってはより多くの情報を載せたいこともあるかもしれません。
サブVIへ文字列を渡すときにコネクタペーンの数を増やすのはコードを書く上でやりづらい(かつ配線がごちゃつく)ので、複数も文字列を渡せるようなクラスタにまとめると便利です。
操作履歴あれこれ
今回紹介したものはサブVIとして機能を持ち、ステートマシンプログラムに組み込める形としていますが、これ以外にも「操作」の履歴を残す方法はいくつかあります。
参考となるのはLabVIEWのヘルプメニューの「サンプルを検索」で開けるNIサンプルファインダで見つけられます。
今回は操作の履歴を表示するプログラムを紹介しました。機能的グローバル変数と呼べるかわかりませんが、シフトレジスタに値をため込み処理することで、今までの内容を履歴として残すという形は、文字列以外でもいろいろと応用できると思うので、参考になればうれしいです。
ここまで読んでいただきありがとうございました。
コメント