【Java】タイピングゲーム制作時のメモ書き

JFrame

JFrameは、四角いウィンドウが表示され、その中に文字やボタンが並ぶアプリを作るときに使う、Javaの標準ライブラリ「Swing」に含まれる。
 →そのため追加のライブラリやプラグインのインストールは不要
タイトルバー、閉じるボタン、最小化ボタンなどOS標準のウィンドウの見た目・機能を持つ。

ウィンドウに表示させたいものは以下の部品を配置していく。(コンポーネントっていうらしい)

  • JLabel(文字表示)
  • JTextField(文字入力欄)
  • JButton(ボタン)

KeyListenerとDocumentListenerの使い分け

入力した文字を検出する方法はいくつかある。今回はKeyListenerとDocumentLintenerについて記述する。

KeyListener

入力文字を監視することができるインターフェース。以下の3つのメソッドをすべて実装する必要がある。

  • keyPressed(KeyEvent e):キーが押された瞬間に呼ばれる
  • keyReleased(KeyEvent e):キーが離された瞬間に呼ばれる
  • keyTyped(KeyEvent e):文字として入力が確定した瞬間(日本語入力などは反映が遅れる場合あり)に呼ばれる

今回のようなタイピングゲームでは、基本的に“keyTyped”か“keyPerssed”を使うことが多く、特に英数字はkeyTypedが扱いやすい。

DocumentLintener

日本語入力をするときに使う。テキストフィールドの中身が実際に変化したことを検知してくれる。英数字・日本語・IME確定後の文字など入力方法を問わず、最終的にテキストフィールドに入った文字列を正しく取得する。

// インポートするもの
import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;

// 使うとき
textField.getDocument().addDocumentListener(new DocumentListener() {
    @Override
    public void insertUpdate(DocumentEvent e) {
        // 文字が追加された時
        System.out.println("現在の入力内容: " + textField.getText());
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        // 文字が削除された時(BackSpaceなど)
        System.out.println("現在の入力内容: " + textField.getText());
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        // 属性が変更された時(プレーンテキストではほぼ使わない)
    }
});

Timerを使って文字の表示時間を制御

入力文字があっていたら「正解!」と表示させたが、次の問題にかぶった。対策として、Timerを使い「正解!」を一定時間表示後自動的に消す方向に変えた。

import javax.swing.Timer; // 時間制限
 if (input.equals(currentAnswer)) {
 ... 
 // 1000ミリ秒(1秒)後に「正解!」の表示を消す
Timer timer = new Timer(1000, e -> resultLabel.setText(" ")); //第1引数:1000ミリ秒後(=1秒後)、第2引数:時間が来たらresultLabel(正解!)を空にする
timer.setRepeats(false); // 1回だけ実行して終わり
timer.start();
}

お手本ローマ字の上にタイピング文字を表示

薄く表示した正解のお手本ローマ字の上に、タイピングした入力文字を表示させた。こうすることで、入力文字が分からなくてもお手本を見れば打てるようになった。

燐華

ちなみに、JLabelを2つ重ねるんじゃなくてGraphicsを使って文字を書くらしい。

実装

  1. JPanelを継承した「クラス名:TypingPanel」を作る
  2. paintComponentというメソッドをオーバーライドし、その中で「お手本文字(薄いグレー)」を描画
    paintComponent:JavaのSwingで画像に図形や文字を書くためのJComponentが持つメソッド
    JComponent:JavaのSwingにおけるボタンやテキストなどのGUI部品(トップレベルコンテナを除く)の基本となる抽象クラス
  3. 同じ位置に、打った部分だけ濃い色で重ね描き
  4. キーが押されるたびにrepaint()を呼んで再描画
    repaint():コンポーネントの見た目を更新し、paintComponentを呼び出すためのメソッド