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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

3回答

10698閲覧

Object.wait()メソッドを使うと処理が続けて実行されない。

mop

総合スコア14

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2015/01/15 08:00

テキストビューに配列の要素であるString文字列を一つずつセットしています。
一文字ずつセットされているのが分かるようにObject.wait()メソッドを使って、一文字追加されるたびにミリ秒待つ処理を入れています。
テキストビューに配列の文字列がミリ秒毎にセットされていく筈なのですが、一時、間があった後に全て同時にテキストビューにセットされるといった動き方をします。
一体何故このような動きをするのでしょうか?
メソッドを直そうにも原因が分からず困っています。
よろしくお願いします。

lang

1public void textmessageset(){ 2 String str = texts[0][0].toString(); 3 char data[] = str.toCharArray(); 4 textmessage.setText(""); 5 for(int i = 0; i < data.length; i++){ 6 //ミリ秒毎にテキストビューにセット 7 sleep(50); 8 String a = textmessage.getText().toString(); 9 String tt = a.toString() + String.valueOf(data[i]).toString(); 10 textmessage.setText(tt.toString()); 11 } 12 } 13 14//ミリ秒待つメソッド 15public synchronized void sleep(long msec) 16 { 17 try 18 { 19 wait(msec); 20 }catch(InterruptedException e){ 21 } 22 }

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

まず、Object.wait()は、synchronized内で別スレッドを待機するのに使う機能です。
スリープ機能として使うのには適していません。
Javaでスリープをする一般的な方法は、Thread.sleep(long)です。

Androidで、今回のケースのような場合は、AsyncTaskHandlerを組み合わせるのが一般的のようです。
また、ご質問とは関係ありませんが、TextViewに文字列を追加する箇所はTextView#append(String)が使えますよ。

lang

1import android.app.Activity; 2import android.os.AsyncTask; 3import android.os.Bundle; 4import android.os.Handler; 5import android.view.Menu; 6import android.view.MenuItem; 7import android.widget.TextView; 8 9public class MainActivity extends Activity { 10 11 Handler handler = new Handler(); 12 13 private class MessageTask extends AsyncTask<String, Void, Integer> { 14 15 @Override 16 protected Integer doInBackground(String... args) { 17 // 非UIスレッドで実行 18 String[] texts = { /* ... テキストの配列 ... */ }; 19 for (String text : texts) { 20 char[] a = text.toCharArray(); 21 for (int i = 0; i < a.length; i++) { 22 appendText(String.valueOf(a[i])); 23 try { 24 Thread.sleep(100L); 25 } catch (InterruptedException e) { 26 throw new RuntimeException(e); 27 } 28 } 29 } 30 return 0; 31 } 32 33 } 34 35 void appendText(final String text) { 36 handler.post(new Runnable() { // UIスレッドで実行 37 @Override 38 public void run() { 39 TextView view = (TextView) findViewById(R.id.textView); 40 view.append(text); 41 } 42 }); 43 } 44 45 @Override 46 protected void onCreate(Bundle savedInstanceState) { 47 super.onCreate(savedInstanceState); 48 setContentView(R.layout.activity_main); 49 new MessageTask().execute(); 50 } 51 52 // 以下略 53 54}

(2015/01/16 01:03, 01:09, 01:32のコメントへの回答)

サンプルコードは、ご質問の問題に焦点を絞って単独で試せるように書いているので、細かいところは応用して使っていただければと思います。
サンプルコードの変数viewtextmessageに読み替えてください。

クラスの外にあるtextsにはMessageTaskからはMainActivity.this.textsでアクセスできると思います。(static classにしているとこれではできませんがstaticでないので)
それよりも、MainActivitygetClickedTextメソッドを作ってそれを呼ぶようにした方が良いかもしれませんね。
具体的には、こんな感じです。

lang

1// MainActivity 2String getClickedText() { 3 return texts[event][click].toString(); 4} 5 6// MessageTask#doInBackground 7String text = getClickedText(); 8char[] a = text.toCharArray(); 9for (int i = 0; i < a.length; i++) { 10 appendText(String.valueOf(a[i])); 11 try { 12 Thread.sleep(100L); 13 } catch (InterruptedException e) { 14 throw new RuntimeException(e); 15 } 16}

textmessage.setTextにつきましては、サンプルコードではview.append(text)としています。textShownew MessageTask().execute()を書いてみるとどうなりますか?

投稿2015/01/15 14:56

argius

総合スコア9388

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mop

2015/01/15 16:03

解答有難う御座います。 現在実装する為にプログラムを書いていたのですが、 MessageTaskクラスの String[] texts = { /* ... テキストの配列 ... */ }; のところで分からないことがあります。 textsという配列がクラスの外にあるためMessageTaskクラスの方で参照できません。 メインアクティビティにあるのはメインアクティビティにあるメソッドでもテキストの配列を参照しているからなのですが。 後、二次元配列の為、コンパイルエラーが出るようなのですが、どのように記述すればよいのでしょうか?
mop

2015/01/15 16:09

済みません追記です。 MainActivity mai = new MainActivity(); String[] texts = (String[]) mai.texts[event][click]; このように記述してみたのですが宜しいでしょうか?
mop

2015/01/15 16:32

何度も済みません。 new MessageTask().execute(); はOnCreate()に書くとしまして、テキストビューに文字をセットする際、今まではtextShow()というメソッドの中にtextmessage.setText(配列)のようにしていたのですが、御回答されましたコードの場合どのようにしてテキストビューに文字をセットするのでしょうか?
argius

2015/01/15 22:17

追記しました。いまコードを書ける環境でないので、分かりにくかったらすみません。
argius

2015/01/16 00:02

追記を修正しました。
mop

2015/01/16 08:33

返信、有難う御座います。 AsyncTaskとHandlerを組み合わせるなんて発想が自分には出来ませんでした。 期待以上のコードを教えていただいて今後のプログラム制作にも、一層やる気が増して来ました。 解答以外の知識までとても参考になりました。
argius

2015/01/16 08:43

UIとの非同期処理は良く使いますが少し難易度が高いので、 初心者の方には最初の難関かも知れません。 自由に使えるようになるには時間がかかると思いますがめげずに頑張って下さい。 素敵なアプリができると良いですね。
argius

2015/01/16 15:45

補足:KSwordOfHasteさんのSwingの例は、AndroidのUIスレッドとの非同期処理という観点と(GUIの非同期処理という点については)本質的には同じです。AndroidでないGUIをお使いの方々にもご理解いただければ幸いです。
mop

2015/01/16 23:37

有難う御座います。励みになります。
guest

0

setTextの結果が実際にビジュアルに反映される(JTextFieldなどの表示に反映される)のはtextmessagesetメソッドの実行が終わり、イベントディスパッチャーへ戻った後に(JTextFieldが更新されたために起動される再描画制御の中で)JTextField.paintComponent()が呼ばれたタイミングになると思います。

つまりsetText()の延長上でpaintComponent()が呼ばれるわけではないので、最終的な内容しか画面上に見えないことになります。もしアニメーション的なことがしたければ、別スレッドで待ちをはさみながらsetText要求をEDTへ投げるということをする必要があると思います。

lang

1void じわじわ設定(String message) { 2 new Thread() { 3 @Override 4 public void run() { 5 try { 6 for (int i = 0; i <= message.length(); i++) { 7 Thread.sleep(50); 8 String s = message.substring(0, i); 9 SwingUtilities.invokeLater(()->textmessage.setText(s)); 10 } 11 } catch (InterruptedException e) {} 12 } 13 }.start(); 14}

追記: 本件にObject#waitは無関係な気がするので普通にThread#sleepで書いています。

投稿2015/01/15 13:49

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mop

2015/01/15 15:08

SwingUtilities.invokeLater(()->textmessage.setText(s)); は何をしているところでしょうか?コンパイルエラーが出てしまうのですが。 最初の方の説明が難しくてもう少し自分の勉強が必要に感じました。 とりあえず、別のスレッドで実行をする方法を模索するなり回答者さんに聞くなりしてみたいと思います。 解答有難う御座いました。
KSwordOfHaste

2015/01/15 16:04

前提環境がandroidなのを見落としてました!自分のコメントは一般OS用のswingでの話しです。混乱させてしまい申し訳ないです。 argiusさんのコメントを拝見するとUIスレッドとは別のスレッドでコントロールを更新するという考え方自体はandroid/swingともに共通のようですが、実装方法が違います。argiusさんのコメントを参照ください。失礼しました。
mop

2015/01/16 07:15

swingのことは分かりませんが、共通の形で実装できることを理解できれば、自分なりに工夫できたと思っています。 そもそも、質問には、直しようがないので原因を知りたいという風に書いていますので、解答自体にはかなり大きな意義がありました。 有難う御座いました。
guest

0

メインスレッド上でwaitしていませんか?
別スレッドでwaitしてHandlerなのでポストしてみてください。

投稿2015/01/15 09:41

omochi

総合スコア410

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mop

2015/01/15 10:37

public void textmessageset() throws InterruptedException{ String str = texts[event][click].toString(); char data[] = str.toCharArray(); textmessage.setText(""); Thread timeWait = new Thread(); for(int i = 0; i < data.length; i++){ timeWait.start(); try{ timeWait.join(); String a = textmessage.getText().toString(); String tt = a.toString() + String.valueOf(data[i]).toString(); textmessage.setText(tt.toString()); }catch(InterruptedException e){ } } } public void run(){ sleep(50); } このような感じでやってみたのですが、上手くいきませんでした。 この場合の別スレッドでwait()させるにはどうすればよいでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問