2016-11-10 5 views
0

私は2007年に書かれたJava Exposureの教科書から課題を出しています。この本には、最近更新されたいくつかのコードが含まれています基本的なもの)。しかし、この中で私は問題に遭遇しています。私がしようとしたのはshowsetVisible(true)に置き換え、FrameJFrameに変更し、gfx.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);を追加するだけです。しかし、これは実際にウィンドウを閉じることはないと気づいた。私が何回もクリックした場合、おそらく1/30で終了しようとします。遅延を10から1に減らした場合、通常は2回以内に閉じます。これはもちろん、delayメソッドがこの不規則な振る舞いを引き起こしていると私に信じさせました。私はThread.sleepを試しましたが、もちろん動作しませんでした。 クローズボタンを押したときにフレームが閉じるようにこのコードを取得する簡単な方法はありますか?存在しない場合、それを行う簡単ではない方法は何でしょうか?ここでこの単純なループがJFrameの問題を引き起こす原因

はコードです:これは、

// Lab30st.java 
// The Screen Saver Program 
// Student Version 


import java.awt.*; 
import java.awt.event.*; 
import java.applet.*; 
import javax.swing.JOptionPane; 


public class Lab30st 
{  
    public static void main(String args[]) 
    { 
     GfxApp gfx = new GfxApp(); 
     gfx.setSize(800,600); 
     gfx.addWindowListener(new WindowAdapter() {public void 
      windowClosing(WindowEvent e) {System.exit(0);}}); 
     gfx.show(); 
    } 
} 


class GfxApp extends Frame 
{ 

    private int circleCount, circleSize; 

    public GfxApp() 
    { 
     circleCount = 50; 
     circleSize = 30; 
    } 


    class Coord 
    { 
     private int xPos; 
     private int yPos; 

     public Coord(int x, int y) 
     { 
      xPos = x; 
      yPos = y; 
     } 
    } 

    public void paint(Graphics g) 
    { 
     int incX = 5; 
     int incY = 5; 
     int diameter = 30; 
     int timeDelay = 10; 
     Circle c = new Circle(g,diameter,incX,incY,timeDelay); 
     for (int k = 1; k <= 2000; k++) 
     { 
      c.drawCircle(g); 
      c.hitEdge(); 
     } 

    } 
} 



class Circle 
{ 
    private int tlX;  // top-left X coordinate 
    private int tlY;  // top-left Y coordinate 
    private int incX;  // increment movement of X coordinate 
    private int incY;  // increment movement of Y coordinate 
    private boolean addX; // flag to determine add/subtract of increment for X 
    private boolean addY; // flag to determine add/subtract of increment for Y 
    private int size;  // diameter of the circle 
    private int timeDelay; // time delay until next circle is drawn 



    public Circle(Graphics g, int s, int x, int y, int td) 
    { 
     incX = x; 
     incY = y; 
     size = s; 
     addX = true; 
     addY = false; 
     tlX = 400; 
     tlY = 300; 
     timeDelay = td; 
    } 

    public void delay(int n) 
    { 
     long startDelay = System.currentTimeMillis(); 
     long endDelay = 0; 
     while (endDelay - startDelay < n) 
      endDelay = System.currentTimeMillis(); 
    } 

    public void drawCircle(Graphics g) 
    { 
     g.setColor(Color.blue); 
     g.drawOval(tlX,tlY,size,size); 
     delay(timeDelay); 
     if (addX) 
      tlX+=incX; 
     else 
      tlX-=incX; 
     if (addY) 
      tlY+=incY; 
     else 
      tlY-=incY; 
    } 


    public void newData() 
    { 
     incX = (int) Math.round(Math.random() * 7 + 5); 
     incY = (int) Math.round(Math.random() * 7 + 5); 
    } 

    public void hitEdge() 
    { 
     boolean flag = false; 
     if (tlX < incX) 
     { 
      addX = true; 
      flag = true; 
     } 
     if (tlX > 800 - (30 + incX)) 
     { 
      addX = false; 
      flag = true; 
     } 
     if (tlY < incY + 30) // The +30 is due to the fact that the title bar covers the top 30 pixels of the window 
     { 
      addY = true; 
      flag = true; 
     } 
     if (tlY > 600 - (30 + incY)) 
     { 
      addY = false; 
      flag = true; 
     } 
     if (flag) 
      newData(); 
    } 

} 
+0

'gfx.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);が正しいです。また、あなたの "遅延"が問題を引き起こしているということも間違いありません。 awt paint()スレッドをブロックしたり、CPUを回転させて遅延を実装したりしないでください。 – BadZen

答えて

2

あなたはイベントディスパッチスレッドを「凍結」されている

public void delay(int n) 
    { 
     long startDelay = System.currentTimeMillis(); 
     long endDelay = 0; 
     while (endDelay - startDelay < n) 
      endDelay = System.currentTimeMillis(); 
    } 

とそのクローズのように(起こるしようとしている他のすべてのものウィンドウ)はスレッドが "スリープ"から出るまで待たなければなりません。 基本的にEDTで遅延を行うべきではありません。別のスレッド上にあるはずです.EDTスレッドに更新を依頼してください。

「ビジー待機」の遅延により、他の問題も発生する可能性があります。あなたはひどいですJava Event-Dispatching Thread explanation

1

を参照してくださいThread.sleep()

を使用して動作を向上させることができます。
コード全体を再構成する必要があります。

本当に悪いから始めましょう: delayは、(ほぼ)忙しい待ちです。私はBASICが近代的なので、忙しい待ちを見たことがありません。それは基本的にスレッドにCPUの人質を保持するだけでなく、他のスレッド(ほとんど)がタイムスライスを使用することはできません。私が言っているのは、システム時間関数を呼び出すと他のスレッドを実行できるコンテキストスイッチが発生しますが、それでもやはり悪いことです。

まだまだかなり悪い: Thread.sleepと交換してください。はい、いいえビジー待つが、あなたはまだ唯一のUIスレッドを保持しています。これは、メインウィンドウを閉じるまでの他のUI作業が発生しないことを意味します。発生する必要があるもの

はドローイベントをトリガし、アニメーションの次の部分を行うために、外部タイマー(例えばjavax.swing.Timer)を取得します。

"Java smooth animation"を検索するには、これを行う方法の例、ダブルバッファー、すべてがあります。

関連する問題