小学校教員のためのプログラミング入門

タイプライタを作る

文字を表示する

 まずは,キーボードの文字キーが押されると,その文字を表示するスケッチを作ってみます.

  表示する文字の取得

 キーボードの文字キーが押されたとき,その文字を取得するには,前回説明したようにイベントハンドラ keyPressed を利用します.なお,文字を格納する変数の型は char です.

 最初は何も表示しないようにするために,スペースを代入します.スケッチのコードの中に文字を値として記述したいとき,たとえば a という文字を記述したいとき,そのまま a と書くと,変数名など識別子の a との区別ができませんので,'a' のようにシングルクォーテーションで文字を囲みます.これを文字リテラルと呼びます.今回は変数にスペースを代入したいので,シングルクォーテーションの間にスペースを書きます.

char keydata = ' ';
      :
void keyPressed()
{
  keydata = key;
}

  フォントの準備

 Processing で文字を表示するには,表示する文字のフォントを生成する必要があります.そのためには,PDE のメニューから,[Tool] - [CreateFont] を選びます.するとダイアログが表示されますので,使いたいフォントの種類とサイズを指定します.

 今回は ArialMT の 24 ポイントを使うことにしてみます.また,どのような文字のフォントを作るかを For... と表示されているところに入力します.今回は英数字を対象とするので,ABCD...XYZabcd...xyz0123456789 あたりを入力します.もしくは [Characters] をクリックした後,[Default Characters] にチェックを入れるのでも構いません.また,下に表示される Filename をコードの中で利用しますので,記録しておいてください.

  文字表示の準備

 作成したフォントを用いて表示をするには PFont クラスのインスタンス(PFontオブジェクト)を生成します.そこで,PFont オブジェクトを格納する変数をグローバル変数として宣言し,setup の中でオブジェクトを生成し,格納するコードを入れます.

PFont font;
  :
void setup()
{
  :
   font = loadFont("ArialMT-24.vlw"); 

  文字の表示

 文字の表示は次のようなコードで行えます.

fill(255);
textFont( font );
text( keydata, 50, 50 );

 fill は塗りつぶし色を指定するメソッドでした.文字の色は fill メソッドで指定します.textFont メソッドはフォントの種類を指定するメソッドで,生成したPFont オブジェクトをパラメータにします.text メソッドは 1 番目パラメータとして渡した文字列を画面上に描くメソッドです.文字列の指定方法は文字列リテラルを直接書く方法と,後に説明する Stringオブジェクトを書く方法があります.また,文字リテラルやchar 型の変数を書くことも可能です.2,3 番目のパラメータで表示する位置を指定します.

 次に,ここまでの説明を元に作成したスケッチを示します.

PFont font;
char keydata = ' ';

void setup()
{
  font = loadFont("ArialMT-24.vlw");
}

void draw()
{
  fill(0);
  stroke(0);
  rect(0,0,width,height);
  
  fill(255);
  textFont( font );
  text( keydata, 50, 50 );
}

void keyPressed()
{
  keydata = key;
}

文字の表示はもちろん draw メソッドの中に入れます.また,毎回文字を描く前に,前に描いた文字を消すために,描画ウィンドウ内を黒で塗りつぶしています.

タイプライタを作ってみる

 先のスケッチは直前に押されたキーの文字を表示するものでしたので,その文字を保存しておくだけで済みました.今回はそれまでに押されたすべての文字を表示する必要があるので,複数の文字を保存しておく必要があります.文字を保存するための変数の型は char 型なので,その配列を用意する方法もありますが,複数の文字,つまり文字列を保存するには String というクラスが用意されています.

 キーが押されたらその文字を String クラスのインスタンス(Stringオブジェクト)に加えていくことになります.String オブジェクト同志や,String オブジェクト char 型の変数に格納されている文字列や文字をくっつける,+ 演算子を使うことができます.String オブジェクト data に,char 型の変数 keydata をくっつけるには,

data = data + keydata;

と書くことができます.なお,String オブジェクトを生成するには

String data;
void setup()
{
  data = new String();

とするか,文字列リテラルを代入します.たとえば,

String data;
void setup()
{
  data = "";

と書くと,空の文字列が入った String クラスのインスタンスが生成されます.

 では,上記のことをふまえて,スケッチを完成させてみましょう.先のスケッチからの変更点としては,キーが押されたら文字列に文字を加える処理にする点,draw の中では文字ではなく文字列を表示する点です.

14-1.jpg

打ち込んだテキストの保存

 次に,打ちこんだテキスト(文字列)をファイルに保存してみます.

 ファイルにデータを書き込むには PrintWriter クラスを用います.そこで,まず PrintWriter オブジェクトを格納するための変数をグローバル変数として宣言します.

PrintWritter output;

 次に,createWriter メソッドを呼び出してオブジェクトを生成します.パラメータはファイル名で,戻り値が PrintWriter オブジェクトになります.今回は setup の中で生成をすることにします.

output = createWriter( "typewriter.txt" );

 データを実際に書き込むときには,PrintWriter クラスのメンバメソッドである print メソッド,および,println メソッドを用います.両者ともパラメータは表示したい値です.後者はデータを書き込んだ後,改行コードも記録してくれます.

 なお,print と println メソッドを呼び出すだけでは,バッファと呼ばれるメモリ上に記憶されるだけで,物理的な記録媒体(たとえばハードディスク)には記録されません.この記録を行いたいときには,同じくメンバメソッドの flush を呼びます.物理的な記録には時間がかかるため,ある程度のデータをバッファにためてから,まとめて物理的に記録する仕組みが用意されているのです.

 今回はキーが押されるたびに,そのキーに対応する文字をファイルに記録することにします.また,改行が押された場合,ファイルの方にも改行コードを記録したいと思います.しかし,Enter キーがおされたときに key に格納されているデータを print メソッドで記録しようとしてもうまくいきません.そこで,Enter キーが押されたときには println メソッドを呼び出すことで,改行コードを記録します.Enter キーが押されたかどうかは,key に格納されている値(文字)を int 型に変換してあげます.すると,押された文字の文字コードが出力されるので,Enter キーに対応する文字コード 10 であるかどうかを判定すればよいことになります.また,Enter キーが押されたタイミングで物理的な記録もすることにしましょう.

if( int( key ) == 10 )
{
  output.println( "" );
  output.flush();
}
else
{
    output.print( key);
}

 データを記録し終えたら,必ず PrintWriter クラスのメンバメソッド close を呼び出します.今回は,プログラム終了時に呼び出される stop メソッドの中で行えばよいでしょう.

void stop()
{
  output.close();
}

 上記をまとめるて完成させたスケッチを実行すると,実行フォルダ(PDE 環境で実行した場合は pde ファイルと同じ場所,ウィンドウズアプリケーションとして実行した場合は exe ファイルと同じ場所)に typewriter.txt というファイルが生成されます.それを開くと,打ち込んだテキスト(文字列)が書き込まれていることを確認できると思います.

テキスト表示スケッチ

 次に示すのは,上で作ったスケッチの逆,ファイルに書き込まれているテキスト(文字列)データを読み込み,画面に表示するスケッチです.

void setup() 
{
  size(300,300);
  background(0);
  
  PFont font = loadFont("Aharoni-Bold-24.vlw");
  textFont(font);
  
  noLoop();  // draw メソッドを呼び出さないようにする
  read();
}

void read()
{
  String data = "";
  String line = "";
  BufferedReader reader = createReader("typewriter.txt");  // 読み込むファイルを設定
  
  while( line != null )  // すべて読み込む(line に null が設定される)までループする
  {
    try 
    {
      line = reader.readLine();  // 1行読み出す
    } 
    catch (IOException e) 
    {
      line = null;  // もしエラーが発生したら,null を設定する
    }
    if( line != null )  // 1行読み出すことに成功したら
    {
      data += line + '\n';  // その1行と改行を,data に加える
    }  
  }

  text( data, 0, 30 );  

  reader.close();
}

  ファイルからの読み出し

 テキストファイルを読み込むには,BufferedReader クラスを使います.createReader メソッドで読み込みたいファイルを指定し,戻り値の BufferReader オブジェクトの readLine メソッドを呼び出すと,そのファイルから1 行の文字列を読み出せます.

 ファイルからすべて文字列を呼び出した後に,再度readLine メソッドを読み出すと,null が戻り値として帰ってきます.そこで,読みだしたデータが null になるまで繰り返し readLine メソッドを呼び出すことで,ファイル内のすべてのデータを読み出すことができます.

 readLine で読み出したデータは String 型の変数 data に加えていっています.読みだしているデータは1行単位なので,加えるときに '\n' を後ろに加えて,表示の際に改行されるようにしています.'\n' は改行を意味する文字です.そして,すべて読み出したら,描画ウィンドウに text メソッドで描画を行っています.

  読み出し時の例外エラー対処

 readLine は 読み込むタイミングによって例外エラーというエラーが発生することがあります.例外エラーが発生するとプログラムの実行が止まってしまいますので,try〜catch 構文というものを使い,この停止を避けることを行います.これは try の部分で例外エラーが発生したら,プログラムの実行は停止させない代わりに,catch の部分のコードを実行するというものです.今回は readLine でエラーが発生したら,変数 line に null を設定しています.こうすることで,エラーが発生したときは,すべてのデータを読み出したと同じとみなして,処理を続けさせています.

  draw メソッドの常時呼び出しの停止

 このスケッチでは,noLoop というメソッドを呼び出しています.連続モードでは draw メソッドが常に呼び出されることになっていますが,noLoop メソッドを呼び出すと,その呼び出しが停止します.このスケッチでは,ファイル内のすべてのデータを読み込んだら,それを描画すればよいだけなので,描画は1回だけで十分です.そのため,draw メソッドの呼び出しを停止して,setup メソッドから呼び出している read メソッド(自分で作成したメソッド)内で,描画を行っています.

 なお,draw メソッドの呼び出しを再開したい場合は,loop メソッドを呼び出します.また,停止中に draw メソッドを1回だけ呼び出したい場合は redraw メソッドを呼び出します.

  メソッドの作成

 read というメソッドが定義されています.これは今まで出てきていないメソッドです.setup や draw のような組み込みメソッドでしょうか.いや,違います.これは自分で新たに定義したメソッドです.このように,ある処理をまとめて一つのメソッドとして定義することができます.そして,定義したメソッドは,その他の部分から自由に呼び出すことが可能です.メソッドの作り方については,また次の機会に詳しく説明します.

課題

 先に説明した,スケッチ終了時に保存が行われるタイプライタスケッチを完成させましょう.

 スケッチ名は半角英数字で 学籍番号_K12 とし,pde ファイルを WebClass から提出してください.