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

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

ただいまの
回答率

90.51%

  • Java

    13836questions

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

  • Javaアプレット

    37questions

    Javaアプレットは、Webページに組み込まれて実行されるJavaアプリケーションの形式です。Java SE 11で廃止となりました。

Javaのアプレットが途中で止まる

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 303

aiueoaiueoaiue

score 74

問題

Javaのアプレットビューワーでタイマーを使った簡単な描画を行いたいのですが、途中までは動くのですが、急に止まってしまいます。自分なりに調べたところペイントメソッドが急に呼ばれなくなっているみたいです。この原因がわかる方、おられましたら回答お願い致します。

ソース

```Java
import java.applet.*;
import java.io.*;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.*;
import java.awt.event.*;

/*
<applet code="test.class" width="150" height="150">
</applet>
*/

public class test extends Applet implements ActionListener{
int X = 75, Y = 30, W = 30, H = 50, K = 10 ;
Timer timer, timer2;
int x;
Button btn = new Button("スタート");
boolean btnClicked = false;

public void  actionPerformed(ActionEvent e){
if (e.getSource() == timer2&&this.btnClicked==true){
x+= 2;
if(x == 8){
x = 0;
}
}
if (e.getSource() == timer&&this.btnClicked==true){

timer2.start();
}
if (e.getSource()==this.btn){
this.btnClicked = true;
this.timer.start();
}
repaint() ;
}
@Override
public void init(){
timer = new Timer(20, this); 
timer2 = new Timer(2, this);
add(this.btn);
this.btn.addActionListener(this);
}

省略

追記

timer2のインスタンスの生成をinitの中で行うことでアプレットは止まらなくなりました。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

論理が不自然な点

timerが何度も発火するようになっていますので、発火の度にtimer2のインスタンスが繰り返し(無限に)生成され、そのたびにタイマーイベントの発火契機が増えていきます。

100や200程度のTimerインスタンスやタイマーイベントが登録された状態になったからといってjavax.swing.Timerのイベント通知機構が破綻するようなやわな作りにはなっていないと思いますが、それでも不必要にTimerインスタンスを生成してしまっているのは問題だと思います。

アニメーションが止まった原因

それについては自分の環境(Windows10, 主記憶8GB, JDK 1.8.0_152)では再現しませんでした。
なお、IDE(IntelliJ IDEA)からのデバッグ実行によりAppletViewerの元で実行しています。

推測ですが、...

(1)timer2にTimer@1のインスタンスが設定されていてイベント発火を待機しているとする
(2)timerが発火してtimer2に新たなTimerインスタンスTimer@2が設定されてしまう
(3)古いインスタンスTimer@1のイベントが発火するがif (e.getSource() == timer2 ...)の判定で、timer2のインスタンスが変わってしまっているためにこの条件文が成立しない。ゆえにアニメーションの更新処理がされずにrepaintのみが実行される。

タイミングによって上記のような現象が起こっているのではないでしょうか?

対処

(A) timerを何度も発火させる必要はない。=>ワンショットタイマーで充分。
この対策が本質的な対策だと思います。

しかし論理をわかりやすくするという意味で気になる点があるのでそちらも変更をお勧めします。

(B) 同一のイベントハンドラーで複数のイベントをまとめてハンドリングしようとすること

Event#getSource()によりイベント発火元に応じた処理を切り分けるという手法は「同じような処理を複数のコンポーネントに対して同一のハンドラーでまとめて処理する」というような場合なら便利です。例えばオセロのようなもので、駒をそれぞれ独立したコンポーネントにしておき、それら全てのクリックイベントを同一のハンドラーで処理するような場合です。イベントソースからどの駒であるかはわかるので、その違いを除き共通的なハンドリングを行いたくなることでしょう。

しかしながら本件ではボタンのクリック、timerの発火、timer2の発火のそれぞれはまったく違う処理ですので無理に一つのハンドラーで処理するのはかえって分かりにくくなると思います。たまたまだとは思いますがgetSource()を使ったために作りこまなくてよいバグを作ってしまったとも言えますし。

具体的にはアプレットのクラスからimplements ActionListenerを取り去り、ActionListenerのインスタンスをthisではなくて、それぞれのイベント設定ごとの個別のリスナー(ハンドラー)を無名クラスやラムダ式やメソッド参照を用いて設定することをお勧めします。

以下、ラムダ式の例を挙げてみます。 (ちなみにbtnClickedというフラグも必要ないように思えますので以下の例では省略してます。)

// Javaではクラス名は必ず大文字で始めましょう。
// 小文字で始めても動きはしますが、習慣に反しているため多くのプログラマーの目には
// 大変奇妙に映ります。
public class Test extends Applet {
  // 定数ならstatic finalの方が良い
  // (プログラムの今後の改造によっては定数ではなくなるのかも知れませんが)
  static final int X = 75, Y = 30, W = 30, H = 50, K = 10 ;
  int x;

  @Override
  public void init() {
    Button btn = new Button("スタート");
    btn.addActionListener(ev -> onStartButtonClicked());
    add(btn);
  }

  // 何がおきたかはっきりわかるようなメソッド名にする
  private void onStartButtonClicked() {
    // timerはこのメソッド以外からさわる必要はないのでフィールドにしなくてよい
    Timer timer = new Timer(20, event -> onAnimationStart());
    timer.setRepeats(false); // ワンショットタイマーにする
    timer.start();
  }

  // 現在のコードではtimer2をフィールドにする必要はないが
  // 後でアニメーションを止めるような処理を追加することを想定すると
  // 元のコードにあるとおり、フィールドにしておいた方がよいでしょう
  Timer timer2;

  private void onAnimationStart() {
    timer2 = new Timer(2, event -> onUpdateAnimationFrame());
    timer2.start();
  }

  private void onUpdateAnimationFrame() {
    ...アニメーション用の状態変更処理...
    repaint();
  }

  ...
}


```

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/14 11:22 編集

    余談ですが、ご質問にあるコードはインデントに空白文字とタブ文字をまぜて使っているためご自分のエディター上ではそろっているように見えてもマークダウンによりタブ幅が変わるとインデントが乱れて見えてしまいます。こうした場で質問する際のコードは「閲覧者に正確にインデントを示し、コードを正確に把握しやすくする」ことに注意を払ってください。不正確なインデントは閲覧者へ無用な混乱を与えます。
    ご質問にあるコードはそれほどの乱れはないですが、ひどい人になると「インデントがない方がまし」なようなハチャメチャなコードを貼り付けておられたりしますのでこうした点にも注意を払うとよいと思います。

    キャンセル

  • 2018/01/14 12:59

    ありがとうございます。timer2のインスタンスをif文の中で生成していたのは最終的にタイマーのスピードを徐々に遅くしようと考えていたからです。そのためにはtimer2 = new Timer(2, this);の2秒遅延の部分を変数にして、いちいちインスタンスを生成していくしかないかなぁと考えていました。この方法が使えないとなると、どのようにすればタイマーのスピードを徐々に遅くするという事が出来るでしょうか?
    ちなみにtimer2のインスタンスの生成をinitの中で行うことでアプレットは止まらなくなり、思い通りの結果になりました。

    キャンセル

  • 2018/01/14 13:11

    なるほど。そういう意図でしたか。

    ところで、回答する際には質問文やその中のコードから読み取れる範囲でコメントするしかありません。おっしゃるとおりの意図があるなら質問文に明記して「なぜこういうコードを書きたかったのか」を示していただけると最初からそれを想定したコメントができます。

    > どのようにすればタイマーのスピードを徐々に遅くするという事が出来るでしょうか?

    これは最初の質問にかかれていませんね?質問の内容を途中であれこれいじるのはよくありません。なぜかというと、質問内容が大きく変化すると編集後の質問内容と回答の内容が不一致になり、一般の閲覧者が「この質問に対してなんでこんな回答してるの?」と混乱するからです。元の質問に充分質問意図が含まれていなかった場合は質問意図を捕捉する意味で編集するのはよいことなのですが、内容が大きく変わってしまう場合は新たに質問を挙げて「知りたいことをより端的に尋ねる」方がよい場合もあります。このあたりの匙加減が難しいかもしれませんね。本件の場合、個人的には新たに質問を起こした方がよいと思います。タイトルを「Appletでアニメーションの時間間隔を徐々に変更したい」というズバリの内容にするといいのではないでしょうか?

    キャンセル

  • 2018/01/14 13:15

    わかりました。ありがとうございました。

    キャンセル

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

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

関連した質問

  • 解決済

    java 画像の表示

    コード import java.applet.Applet; import java.awt.*; public class sample extends Applet{    

  • 解決済

    アプレット パネル

    javaアプレットを勉強しています。 パネルを作って、そこに画像を張り付けて表示させたいと思っています。 ですが、実行しても表示されません。 パネルに画像を張り付けることはできない

  • 解決済

    国旗を表示させるアプリケーションを作りたい

    前提・実現したいこと グローバル変数としてflagを宣言し、メソッドpublic void actionPerformed(ActionEvent e)において、どのボタンが押さ

  • 解決済

    国旗を表示させたい(続き)

    前提・実現したいこと btn [0][1][2]をクリックすると、それに対応した国旗が表示されるようにしたい。 ソースコード import java.awt.*;   

  • 解決済

    javaの印刷ダイアログを表示した際のプロパティボタンを非表示にしたい

    お世話になります。 タイトルの通り、javaの機能で印刷ダイアログを表示させる機能があるのですが、そのダイアログの中にあるプロパティボタンを非表示、または使用不可にしたいです

  • 受付中

    【至急】javaの課題でエラーが消えずコンパイルが通りません。

    前提・実現したいこと 学校で銀行口座を作ると言う課題が出されているのですが、一個のエラーがどうやっても消えず悩んでいます。 言語はjavaです。 課題内容は (1) こ

  • 解決済

    java eclipseについて

    java eclipseでスライドパズルを作成しています。 9枚の画像で作成しており、現在は9枚の画像を実行するたびにランダムで表示するところまでいきました。 その後ですが9枚

  • 受付中

    Javaでフレーム内にランダムに数値を表示させたい

    前提・実現したいこと スロットゲームにてボタン入力後ターミナルではなくフレームにランダムな3桁を入力したい。 あわよくば数値によっては言葉を表示させたい。 777ならばBig Bo

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

  • Java

    13836questions

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

  • Javaアプレット

    37questions

    Javaアプレットは、Webページに組み込まれて実行されるJavaアプリケーションの形式です。Java SE 11で廃止となりました。