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

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

ただいまの
回答率

88.80%

repaint()を即時実行したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 634

Mats_k

score 11

前提・実現したいこと

Java初心者です。初めての質問のため、質問の仕方、調べ方なども含めアドバイスをいただけると幸いです。

今回、Javaアプレットでコマンド入力した長方形データを即時アプレット表示するプログラムを作っています。
run()メソッドが呼び出される度に「Applet表示」の出力がされているものの、repaint()が操作の終了後にしか実行されませんでした。

少し調べてみたところ、repaint()は再描画を要求しているだけに過ぎず、repaint()と書いた場所で即時に再描画されるわけではないということはわかりました。

そこで、具体的にすぐ再描画してほしい場合はどうすればいいのでしょうか?
稚拙な質問で申し訳ございません。よろしくお願いします。

該当のソースコード

import java.applet.Applet;
import java.awt.*;

public class RectangleEditor extends Applet {      
    Command command = new Command();
   //コマンド入力操作を行うクラスへ受け渡し
    public void init(){
        command.choseCommand();     
    }

  //他クラスから呼び出しされるメソッド
    public void run(){   
        System.out.println("Applet表示");
        repaint();
    }


    //長方形のデータを受け取り、描画する
    public void paint(Graphics g) {
        Board board = new Board();  //長方形データを格納しているクラス
        int[] x = board.xList();
        int[] y = board.yList();
        int[] w = board.wList();
        int[] h = board.hList();
        String[] color = board.cList();

        for(int rectNumber = 0; rectNumber < board.isList(); rectNumber ++){ 
            if(color[rectNumber].equals("red")){
                g.setColor(Color.red);
            }else if(color[rectNumber].equals("blue")){
                g.setColor(Color.blue);
            }else if(color[rectNumber].equals("yellow")){
                g.setColor(Color.yellow);
            }else if(color[rectNumber].equals("gray")){
                g.setColor(Color.gray);
            }

            g.fillRect(x[rectNumber],y[rectNumber],w[rectNumber],h[rectNumber]);
        }
    }  
}

試したこと

repaint();の後に、Thread.sleep(10000);を追加して時間の間隔を開けましたが、
結果は変わりませんでした。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

まず最初にプログラミングの大前提について提案したいことがあります。アプレットによるGUIはやめることをお勧めします。質問者さんの目的にもよりますが

・JavaによるスタンドアロンのGUIアプリケーションを作ってみる
=> swingないしはJavaFXを学ぶことをお勧めします。
・Webブラウザー上でGUIアプリケーション的なものを作ってみる
=> HTMLとJavaScriptを学ぶことをお勧めします。
・Java(的な言語)を用いて簡単にGUIアプリケーションを作ってみる
=> Processingをお勧めします。

さて、Applet(のサンプルとしてよくあるプログラムコード)に最も近いのはswingライブラリーによるスタンドアロンアプリケーションですのでそれを用いた例で本件についてコメントしてみますと・・・

swingのアプリケーションはイベントディスパッチ方式という仕組みで動いています。

swing内部
   |
   <---- ユーザーの操作により発生するイベント
   |
   ----> そのイベントの処理をするハンドラーメソッド
   <----
   |
   <---- 時間経過により発生するイベント
   ----> そのイベントの処理をするハンドラーメソッド
   <----
   |
   ...


こんなふうにプログラムの主制御はswing内部のあるメソッドが司っており、これをアプリケーションに書いたどこかのメソッドで以下のようなことをしようとしても

例1:

swing内部
   -----> どこかのメソッド
             |
             ----> repain的な何か(A1)
             ----> repain的な何か(A2)
   <----     +
   |
   (B) -> 再描画される(paintが呼ばれる)
   ...


(B)の時点までは実際の描画は行われません。(A1),(A2)では「次にswing内部に戻った時に再描画が必要であるということを覚えておくこと」しかできないのです。

なるべく即座にそれが反映されるようにするためにはswingを暇な状態にしてやらねばなりません。暇な状態というのは前述したevent-dispatch-loopに「戻る」ことを意味します。つまり(A1)で指示したrepaintの効果(再描画)を速やかに得たいなら(A1)をした後即座にswingへ戻らねばなりません。

例2:

swing内部
   -----> どこかのメソッド
             |
             ----> repain的な何か(A1)
   <-----    +
   (B) -> 再描画される(paintが呼ばれる)
   |
   ------> どこかのメソッド
             ----> repain的な何か(A2)
   <----     +
   (B) -> 再描画される(paintが呼ばれる)
   ...

例2のようにするには「どこかのメソッド」がしかるべきタイミングでswing内部から「呼び出してもらう」ことが必要です。典型的には「どこかのメソッド」はあるイベントにより起動されるハンドラーメソッドとして作る必要があります。ごく短い時間に連続してイベントを発生するにはjavax.swing.Timerなどのクラスを用いるとよいでしょう。

ただ、あなたがスレッドプログラミングを学ぶと例1に近い感覚でプログラミングすることもできます。でもそれを例2のようなswingのevent-dispatch-loop方式でのプログラミングをよく把握しないままやっても正しいプログラミングは難しいと思います。まずは例2の制御方式を学ぶことをお勧めします。


ご質問のコードは一部の抜粋なのでどういう制御をしようとしているかがはっきりわかりません。それがもう少し(充分短いコードで)提示されれば具体的な制御案のアドバイスが得られると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/05 13:51

    たくさんのアドバイスと丁寧な回答をありがとうございます。
    大学で教わったことがなかったので、とても助かりました。
    Boardクラス(長方形の格納クラス)
    ,,,
    import java.util.LinkedList;
    import java.util.List;

    public class Board{
    static private int newListNumber = 0; //格納されている長方形の個数
    static RectangleEditor re = new RectangleEditor();
    static Command command = new Command();
    Rectangle[] rect = new Rectangle[1]; //入力された長方形を一時格納する配列

    static List<String> list = new LinkedList<String>();
    static List<Integer> w = new LinkedList<Integer>();
    static List<Integer> h = new LinkedList<Integer>();
    static List<Integer> x = new LinkedList<Integer>();
    static List<Integer> y = new LinkedList<Integer>();
    static List<String> c = new LinkedList<String>();

    //リストに長方形を追加する
    static public void add(ColorRectangle[] rect){
    list.add(rect[0].toString());
    w.add(rect[0].width());
    h.add(rect[0].height());
    x.add(rect[0].x());
    y.add(rect[0].y());
    c.add(rect[0].c());
    newListNumber++;
    System.out.println("長方形を新たに追加できました");
    command.displayBoard();
    re.run();
    command.choseCommand();
    }

    //リストの長方形を削除する
    static public void delate(int numberRect){
    //格納番号以外の数値を入力した場合のエラー処理
    if(newListNumber <= numberRect || numberRect < 0){
    System.out.println("指定された番号に長方形は存在しません。番号をもう一度確認してください。");
    command.delate();
    }else{
    //該当の長方形の各データの削除
    list.remove(numberRect);
    x.remove(numberRect);
    y.remove(numberRect);
    w.remove(numberRect);
    h.remove(numberRect);
    c.remove(numberRect);
    newListNumber--;
    System.out.println("指定の長方形を削除できました");
    command.displayBoard();
    re.run();
    command.choseCommand();
    }
    }
    .....(略)
    ,,,

    Commandクラス(コマンド入力の指示)
    ,,,
    public class Command{
    Input input = new Input();
    ColorRectangle[] rect = new ColorRectangle[1];
    Board board = new Board();

    //コマンドの入力
    public void choseCommand(){
    this.displayCommand();
    int command = input.inputInteger("上記の操作のいずれかを入力してください");
    //入力されたコマンドの条件分岐
    switch(command){
    case 1:
    this.displayBoard();
    this.choseCommand();
    break;
    case 2:
    this.exit();
    break;
    case 3:
    this.create();
    break;
    case 4:
    this.delate();
    break;
    case 5:
    this.move();
    break;
    case 6:
    this.expand_shrink();
    break;
    case 7:
    this.delateAll();
    break;
    default:
    System.out.println("指定外の整数を入力しています。番号を確認した上で、再度入力をお願いします。");
    this.choseCommand();
    }
    }
    //長方形の作成(create)
    public void create(){
    Board board = new Board();
    int dataNumber = 4;
    int[] data = new int[dataNumber];

    //幅、高さ、左上隅座標の入力を要求する
    System.out.println();
    System.out.println("幅(data[0])、高さ(data[1])、左上隅座標(x座標(data[2])、y座標(data[3]))を順に入力してください");

    Input input = new Input();
    for(int i = 0; i < dataNumber; i++){
    data[i] = input.inputInteger("data[" + i + "]:");
    }

    String color = choseColor();
    while(color.equals("")){
    color = this.choseColor();
    }

    //Rectangleクラスにデータの読み込み
    this.rect[0] = new ColorRectangle(data[0],data[1],data[2],data[3],color);
    System.out.println("入力値: " + this.rect[0]);

    //エラー処理
    String error = this.isError(this.rect);
    if(error.equals("false")){
    //Boardに長方形を入力
    board.add(this.rect);
    }else{
    this.choseCommand();
    }
    }

    //長方形を削除する(delate())
    public void delate(){
    //長方形が格納されているか確認する
    if(board.isList() == 0){
    System.out.println("リスト内に長方形が存在しません。4以外のコマンドを選択してください。");
    this.choseCommand();
    }else{
    //削除する長方形を選択し、Boardクラスのdelate()へ処理を渡す
    System.out.println();
    board.showRect();
    int listNumber = input.inputInteger("上記のリストの中で削除したい長方形の番号を半角数字で答えてください");
    board.delate(listNumber);
    }
    }
    ...(略)
    ,,,
    一部抜粋していますが、こちらがRectangleEditorクラスに直接関わりのあるクラスになります。
    見づらいプログラムで申し訳ございません。

    ぜひおすすめしていただいたswingのevent-dispatch-loop方式でのプログラミングを作成したいのですが具体的にどのように制御すればよいのか、どのように調べればよいのかアドバイスいただけたら幸いです。

    キャンセル

  • 2019/05/05 20:02 編集

    えーと・・・本サイトのような場で質問するには長すぎるコードです。またコードをコメント欄に書くのは避けましょう。字下げもされずみづらいことこの上なしです。「字下げのないコードは見る気がしない」というプログラマーは多いです。質問の仕方をアドバイスしますと「余計な処理をそぎ落とし最低限の問題が再現する小さなコードをまず作り、それを省略せずに質問本文に提示すること」です。目安は100行ぐらい。本質問の要点が何かをよく考え必要最小限のコードにしてみることをまずお勧めします。

    キャンセル

  • 2019/05/05 23:43

    本当に常識知らずすぎて申し訳ないです…
    丁寧に教えてくださり、本当にありがとうございます。
    また別途コードの書き方に気をつけて質問させていただきます。

    キャンセル

  • 2019/05/06 00:13

    コメント欄でインデントを気にせず長いコードを書いてしまうといったことは割とよくあることです。自分ははっきりと指摘した方が伝わり易いと考えたのですが、表現がちょっと紳士的でなかったと思います。その点は失礼しました。指摘自体は本サイトの多くの閲覧者に賛同していただける内容と思いますのでくみ取っていただければ幸いです。

    キャンセル

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

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

関連した質問

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