Java Basic GUI作成〜コマンドを入力する〜

イントロダクション

前回は、カーソルを上下に移動しないように修正しました。
今回は、入力した文字を取得します。
入力した文字はコマンドとして使用したいので
入力した文字列は「コマンド」と呼ぶことにします。

・テキストエリアからコマンドを取得する
・カーソルが「Cmd $ >」に被らないようにする

実装しているコードはGITにあります。

設計〜修正する場所〜

エンターキーを押下した時にコマンドを取得、実行する想定
なので、エンターキーを押下した時の処理を修正します。
下のコードでは赤くしている部分です。

前回までのコード

public class CmdView extends Application {
    /** 画面の横サイズ */
    private static final int VIEW_WIDTH = 300;
    /** 画面のたてサイズ */
    private static final int VIEW_HEIGHT = 300;
    /** コマンドの入力開始文字 */
    private static final String CMD_START = "Cmd $ ";
    /** 改行コード */
    private static final String LINE_SEPARETOR = System.getProperty("line.separator");
    /** 入力前のカーソル位置 */
    private int cursorPos;

    @Override
    public void start(Stage primary) {
        TextArea area = createTextArea();
        Group root = new Group();
        root.getChildren().add(area);
        Scene scene = new Scene(root, VIEW_WIDTH, VIEW_HEIGHT);
        primary.setScene(scene);
        primary.show();
    }

    /**
     * TextAreaを作成して返却する
     * @return TextArea
     */
    private TextArea createTextArea() {
        TextArea area = new TextArea();
        // 縦横の幅を設定する
        area.setPrefWidth(VIEW_WIDTH);
        area.setPrefHeight(VIEW_HEIGHT);
        area.setOnKeyPressed(createKeyPressEvent());
        // 初期表示文字を設定する
        area.setText("Hello user please input command!" + LINE_SEPARETOR + CMD_START);
        // テキストエリアの文字列数
        int textLen = area.getText().length();
        // 初期カーソル位置
        cursorPos = textLen;
        area.positionCaret(textLen);

        return area;
    }

    private EventHandler<KeyEvent> createKeyPressEvent() {
        return new EventHandler<KeyEvent>() {
            public void handle(KeyEvent evt) {
                // テキストエリアを取得する
                TextArea src = (TextArea) evt.getSource();
                // 入力を無効にする
                if (isDisabledInput(evt)) {
                    System.out.println("*** isDisable ***");
                    resetCursor(src);
                    return;
                }
                                
                if (KeyCode.ENTER.equals(evt.getCode())) {
                    // テキストエリア内の文字列を全て取得
                    String allText = src.getText();
                    // "Cmd $ "の文字列の位置を取得
                    int startPoint = allText.indexOf(CMD_START);
                }
                
                cursorPos = src.getCaretPosition();
                // チェック用のコンソール出力処理
                System.out.println("EventType: " + evt.getCode());
                System.out.println("Input: " + evt.getCharacter());
            }
        };
    }

    /**
     * キーボードより入力したキーで受け付けないものを<BR/>
     * 判定する
     * @param evt
     * @return true: 受け付けない入力  /  false: 受け付ける入力
     */
    private boolean isDisabledInput(KeyEvent evt) {
        boolean isDisable = false;
        // 入力許可キーのKeyCodeリスト
        List<KeyCode> acList = createAcceptList();

        // チェック処理: 入力禁止するキーの有無をチェック
        return acList.contains(evt.getCode());
    }
    /**
     * プロパティファイル、キーを指定して対象のプロパティを<BR/>
     * 取得する
     *
     * @param propNane プロパティファイル名
     * @param key プロパティのキー
     * @return プロパティの値
     */
    @Deprecated // 使用しないメソッド
    private String getTargetProperty(String propNane, String key) {
        String propStr = null;
        return propStr;
    }

    /**
     * チェック用のリストを作成して返却します<BR/>
     * 入力禁止のKeyCodeを追加
     * @return チェック用のリスト
     */
    private List<KeyCode> createAcceptList() {
        List<KeyCode> acList = new ArrayList<KeyCode>();
        acList.add(KeyCode.UP);
        acList.add(KeyCode.DOWN);

        return acList;
    }

    /**
     * カーソルの移動をしないようにします。
     * @param src
     */
    private void resetCursor(TextArea src) {
        // 始めのカーソル位置を設定する
        src.positionCaret(cursorPos);
    }


    /** メインメソッド */
    public static void main(String[] args) {
        launch();
    }
}

今回の追加修正する場所

・エンターキーを押下した時に入力した文字列を取得する
・エンターキーを押下した後に「Cmd $ >」を追加する
※実装済みなので修正しないが範囲に入るので。。。
・カーソルを横に動かした時に「Cmd $ >」に入らないようにする

追加したコード(抜粋)

修正した部分になりますが、テキストエリアの取得位置を変更

// テキストエリアを取得する
TextArea src = (TextArea) evt.getSource();

エントーキーを押下した時の処理を変更

if (KeyCode.ENTER.equals(evt.getCode())) {
    // テキストエリア内の文字列を全て取得
    String allText = src.getText();
    String command = getCommand(allText);
    src.setText(allText + CMD_START);
    // "Cmd $ "の文字列の位置を取得
    System.out.println("Command: " + command);
    cursorPos = allText.length() + CMD_START.length();
    src.positionCaret(cursorPos);
}

余計な処理になったので以下の処理を削除

// テキストエリアのカーソル位置をフィールド変数にセット
cursorPos = src.getCaretPosition();

左の矢印を入力した時のハンドル
(どのような振る舞いをするか?)をする処理を修正

if (KeyCode.LEFT.equals(evt.getCode())) {
    // 左の矢印が押下された時
    src.positionCaret(cursorPos);
}

最終的なコード

public class CmdView extends Application {
    /** 画面の横サイズ */
    private static final int VIEW_WIDTH = 300;
    /** 画面のたてサイズ */
    private static final int VIEW_HEIGHT = 300;
    /** コマンドの入力開始文字 */
    private static final String CMD_START = "Cmd $ >";
    /** 改行コード */
    private static final String LINE_SEPARETOR = System.getProperty("line.separator");
    /** 入力前のカーソル位置 */
    private int cursorPos;

    @Override
    public void start(Stage primary) {
        TextArea area = createTextArea();
        Group root = new Group();
        root.getChildren().add(area);
        Scene scene = new Scene(root, VIEW_WIDTH, VIEW_HEIGHT);
        primary.setScene(scene);
        primary.show();
    }

    /**
     * TextAreaを作成して返却する
     * @return TextArea
     */
    private TextArea createTextArea() {
        TextArea area = new TextArea();
        // 縦横の幅を設定する
        area.setPrefWidth(VIEW_WIDTH);
        area.setPrefHeight(VIEW_HEIGHT);
        area.setOnKeyPressed(createKeyPressEvent());
        // 初期表示文字を設定する
        area.setText("Hello user please input command!" + LINE_SEPARETOR + CMD_START);
        // テキストエリアの文字列数
        int textLen = area.getText().length();
        // 初期カーソル位置
        cursorPos = textLen;
        area.positionCaret(textLen);

        return area;
    }

    private EventHandler<KeyEvent> createKeyPressEvent() {
        return new EventHandler<KeyEvent>() {
            public void handle(KeyEvent evt) {
                // テキストエリアを取得する
                TextArea src = (TextArea) evt.getSource();
                // 入力を無効にする
                if (isDisabledInput(evt)) {
                    System.out.println("*** isDisable ***");
                    resetCursor(src);
                    return;
                }
                if (KeyCode.ENTER.equals(evt.getCode())) {
                    // テキストエリア内の文字列を全て取得
                    String allText = src.getText();
                    String command = getCommand(allText);
                    src.setText(allText + CMD_START);
                    // "Cmd $ "の文字列の位置を取得
                    System.out.println("Command: " + command);
                    cursorPos = allText.length() + CMD_START.length();
                    src.positionCaret(cursorPos);
                }
                if (KeyCode.LEFT.equals(evt.getCode())) {
                    // 左の矢印が押下された時
                    src.positionCaret(cursorPos);
                }
                // チェック用のコンソール出力処理
                System.out.println("EventType: " + evt.getCode());
            }
        };
    }

    /**
     * キーボードより入力したキーで受け付けないものを<BR/>
     * 判定する
     * @param evt
     * @return true: 受け付けない入力  /  false: 受け付ける入力
     */
    private boolean isDisabledInput(KeyEvent evt) {
        boolean isDisable = false;
        // 入力許可キーのKeyCodeリスト
        List<KeyCode> acList = createAcceptList();

        // チェック処理: 入力禁止するキーの有無をチェック
        return acList.contains(evt.getCode());
    }
    /**
     * プロパティファイル、キーを指定して対象のプロパティを<BR/>
     * 取得する
     *
     * @param propNane プロパティファイル名
     * @param key プロパティのキー
     * @return プロパティの値
     */
    @Deprecated // 使用しないメソッド
    private String getTargetProperty(String propNane, String key) {
        String propStr = null;
        return propStr;
    }

    /**
     * チェック用のリストを作成して返却します<BR/>
     * 入力禁止のKeyCodeを追加
     * @return チェック用のリスト
     */
    private List<KeyCode> createAcceptList() {
        List<KeyCode> acList = new ArrayList<KeyCode>();
        acList.add(KeyCode.UP);
        acList.add(KeyCode.DOWN);

        return acList;
    }

    /**
     * カーソルの移動をしないようにします。
     * @param src
     */
    private void resetCursor(TextArea src) {
        // 始めのカーソル位置を設定する
        src.positionCaret(cursorPos);
    }

    private String getCommand(String text) {
        String[] lines = text.split(LINE_SEPARETOR);
        String target = lines[lines.length - 1];
        return target.substring(CMD_START.length());
    }
    /** メインメソッド */
    public static void main(String[] args) {
        launch();
    }
}

以上のような形で実装してみました。
現状では、以下のような感じでコマンドの入力途中で
エンターキーを押下すると文字が中途半端に切れてしまいます。

そこの部分は次回修正したいともいます。

でわでわ。。。