質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.35%

TextAreaに入力してもらった値を取得したい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,808

score 21

タイトルの通りです。
このクラスは、プレイヤーに練習メニューを選んでもらい、練習を実行するという流れなのですが、TextAreaにプレイヤーに記入してもらったあと、エンターキーで読み込むにはどうしたらいいんでしょうか。
現状Mainメソッドを呼び出しても動きません。

一応流れとしては、Frame1クラスのフレームを作り、その後Frame1からこのMainメソッドを呼び出そうとしています。

public class Main extends JFrame implements MouseListener{

    public static void main(String args[]){
        Frame1 frame1 = new Frame1("パワプロくん");
        frame1.setVisible(true);
    }

    public JTextArea mainArea;
    Scanner input = new Scanner(System.in);  
    JMenuItem menuitem1;
    JMenuItem menuitem2;
    JMenuItem menuitem3;
    String userName = "";

    ByteArrayOutputStream bytes = new ByteArrayOutputStream() {
        public synchronized void flush() throws IOException {
            mainArea.setText(toString());
        }
    };

    PrintStream out = new PrintStream(bytes, true);

    Main(String title, String name){
        userName = name;
        this.setTitle(title);
        this.setSize(624, 580);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.addMouseListener(this);

        JPanel pane1 = new JPanel();
        ImageIcon icon1 = new ImageIcon("背景.jpg");
        JLabel label1 = new JLabel(icon1);
        pane1.add(label1);

        JPanel pane2 = new JPanel();

        mainArea = new JTextArea("");
        mainArea.setPreferredSize(new Dimension(580, 150));
        mainArea.setEditable(true);
        mainArea.setLineWrap(true);
        mainArea.setBorder(new EtchedBorder(EtchedBorder.LOWERED));

        pane2.add(mainArea);

        JPanel pane3 = new JPanel();

        pane3.add(pane1);
        pane3.add(pane2);
        pane3.add(menubar);
        Container con = this.getContentPane();
        con.add(pane3);

        Story(userName);
    }

    private void Story(String name) {
        userName = name;
        Hero h = new Hero(userName);
        System.setErr(out);
        System.setOut(out);
        System.out.println(userName + "「嫌な夢にうなされたな、、、」");
        System.out.println(userName + "「でも確かにその通りだ。今日から必死に練習しよう」");
        boolean done = false;
        boolean doit = false;
        int mon = 9;
        int day = 1;
        Scanner scanner = new Scanner(System.in);
        while(!done){
            String Days = mon + "月" + day + "日";
            while(!doit){
                bytes.reset();
                mainArea.setText("");
                System.out.println(Days);
                System.out.println("(1)筋力, (2)打撃, (3)守備, (4)投げ込み, (5)変化球, (6)走り込み");
                try{
                    System.out.println("今日はどうしようか(練習番号を入力): ");
                    int cmd = scanner.nextInt();
                    if(cmd >= 1 && cmd <= 6){
                        doit = true;
                        h.practice(cmd);
                        done = true;
                    }
                    else{
                        bytes.reset();
                        mainArea.setText("");
                        System.out.println("練習する気がないのか!");
                    }
                }catch(InputMismatchException e) {
                    bytes.reset();
                    mainArea.setText("");
                    System.out.println("練習する気がないのか!");
                }
            }//while(doit)     
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KSwordOfHaste

    2018/01/31 18:04 編集

    JTextAreaには色々な内容が各行に出力されていきますけど、取り出したいのはJTextArea上にユーザーが入力した行だけ(典型的には最後の行)なのですよね?

    キャンセル

回答 2

checkベストアンサー

+1

コメントにちょっと書いたのですが・・・
もしJTextArea上で一般のターミナルソフトでの入力のように一行ずつ入力させようとすると結構面倒な処理を書かなければなりません。非常に大雑把に書いても以下のような少々面倒な実装が必要になります。
(なお以下は質問者さんの元々のプログラムとは独立しており、動作を確認するのに必要であろうJScrollPaneを追加している点を除きJTextArea上でENTERによる行入力を実現する機能のみに絞って書いています)

import javax.swing.*;
import javax.swing.text.BadLocationException;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class TextInputSample extends JFrame {
    public static void main(String[] args) {
        new TextInputSample().setVisible(true);
    }

    TextInputSample() {
        super("sample");
        textArea = new JTextArea(10, 20);
        textArea.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent ev) {
                if (ev.getKeyChar() == '\n') {
                    onEnter();
                }
            }
        });
        JScrollPane scrollPane = new JScrollPane(textArea,
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
            JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        add(scrollPane, BorderLayout.CENTER);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
    }

    JTextArea textArea;

    void printf(String format, Object... args) {
        String text = String.format(format, args);
        textArea.append(text);
    }

    void onEnter() {
        int pos = textArea.getCaretPosition();
        assert pos > 0; // ENTER入力後には必ず1以上になるはず
        try {
            int lineNumber = textArea.getLineOfOffset(pos - 1);
            int startPos = textArea.getLineStartOffset(lineNumber);
            String text = textArea.getText(startPos, pos - 1 - startPos);
            printf("user input: '%s'%n", text);
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
    }
}


「大雑把」と書きましたがそれは一般のターミナルソフトと違って、カーソルを上の行へ移動してENTERを押すとその行全体の内容を「あたかもユーザーがタイプしたかのように」勘違いしてしまう点です。大抵のターミナルソフトではカーソルを上へ移動できても「既に出力された行を編集できない」ようになっていてそこでENTERを押すと最終行にその行をコピーした状態になるといった特殊な動作をします。JTextAreaっていうのは要するに単なるテキストエディターであってターミナルソフトのような行入力指向の機能にはなっていないのでこうした面倒なことを設計しなくてはならないのです。

一応コードは貼りましたが「こうすればよい」というつもりはなく、「こんな面倒な実装をわざわざJTextAreaでやるべきではない」というのが自分の意見です。

行単位での入力をさせたいならもっとシンプルな方針を立てた方がよいと思います。例えばJTextFieldを用いて入力させた方がプログラムはずっと単純ですしユーザーだってどう操作すればよいかわかりやすいのではないでしょうか?JTextAreaを用いるとしてもそれは出力専用とすることをお奨めしたいです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/02/01 02:11

    初心者の私にも分かりやすい説明でとても納得できました。わざわざコードもかいていただき、ありがとうございます。やっとコードも理解できました。
    おっしゃる通り、TextAreaに入力してもらうというのがナンセンスだと思いましたので、方法を変えてみようと思います。ありがとうございました。

    キャンセル

  • 2018/02/01 02:45 編集

    うーん、ナンセンスではないと思います。多少サボった実装でもどう使えばよいかわかっている自分専用のアプリならまぁまぁ使える場合もあるでしょう。
    自分で使うにしても実装がちょっとめんどくさいのがネックではありますね。
    いずれにせよ他の人に使ってもらうなら分かり易い操作にしないとかえって使いづらくなりがちなのでそれが単純な機能・実装をお奨めする理由です。

    キャンセル

+1

拙作ですが、以前、こういうのを作ってみました。参考になるかもしれません。
メモ帳

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/02/01 02:07

    ありがとうございます。自分には難しいですが勉強させていただきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る