2012-02-14 9 views
2

私はJavaを学んでいます。これは私の最初のアニメーションです。スタートボタンを押すとボールが上下に連続的に動き、停止ボタンを押すとボールはSTOPになります。私が書いたコードはボールを5回動かす(3回、2回)。しかし、パネルには開始位置と最終位置のみが表示され、中間位置は表示されません。どのように中間の位置を表示するには?基本アニメーションが実行されない

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

public class dabble 
{ 
    private boolean z = true; 
    private int x=10; 
    private int y=10; 
    private JFrame frame; 
    private JLabel label; 
    private mypanel panel; 
    private JButton b1; 
    private JButton b2; 

    public static void main (String[] args) 
    { 
     dabble dab = new dabble(); 
     dab.start(); 
    } 

    void start() 
    { 
     frame = new JFrame(); 
     label = new JLabel(); 
     panel = new mypanel(); 
     b1= new JButton("Start"); 
     b2= new JButton("Stop"); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     b1.addActionListener(new al1()); 
     b2.addActionListener(new al2()); 

     frame.getContentPane().add(BorderLayout.NORTH,b1); 
     frame.getContentPane().add(BorderLayout.SOUTH,b2); 
     frame.getContentPane().add(BorderLayout.CENTER,panel); 
     frame.getContentPane().add(BorderLayout.EAST,label); 
     frame.setSize(600,600); 
     frame.setVisible(true); 
    } 

    void go() 
    { 
     for(int i=0;i<5;i++) 
     { 
      if(z==false) 
       break; 
      //label.setText("Hi"); 
      y=510-y; 
      panel.repaint(); 
      try{ 
       Thread.sleep(500); 
       //label.setText("sleep"); 
      }catch(Exception Ex) 
      { 
      //label.setText("exp"); 
      } 
     } 
    } 

    class al1 implements ActionListener{ 
     public void actionPerformed(ActionEvent event){ 
      go(); 
     } 
    } 

    class al2 implements ActionListener{ 
     public void actionPerformed(ActionEvent event){ 
      z=false; 
     } 
    } 

    class mypanel extends JPanel 
    { 
     public void paintComponent (Graphics g) 
     { 
      g.setColor(Color.white); 
      g.fillRect(0,0,this.getWidth(),this.getHeight()); 
      int red = (int) (Math.random()*255); 
      int green = (int) (Math.random()*255); 
      int blue = (int) (Math.random()*255); 
      Color c1 = new Color(red,green,blue); 
      g.setColor(c1); 
      g.fillOval(x,y,20,20); 
     } 
    } 
} 
+0

あなたのコードをインデントすると考えられましたか? – aioobe

+2

「コードを書く方法」を学ぶ必要があります。コーディングスタイル、命名規則を学び、それに従ってください。 –

+0

私は悪いコードの書き込みを後悔します。@Ademibanありがとう –

答えて

0

ループを5回(無限ループではなく)実行します。さらに、垂直位置を10から500に変更してから10などに戻します。中間位置を表示したい場合は、中間位置を再描画し、yの中間値を指定することを検討する必要があります。

OK、次の操作を実行すると、あなたの問題を解決しますが、それは間違いなく貧しいデザインです:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class dabble { 

    private static final long ANIMATION_DURATION = 5000; // 5 seconds 
    private static final int REFRESH_RATE = 10;// 10 times per second 
    private boolean incrementing = true; 
    private volatile boolean z = true; 
    private int x = 10; 
    private volatile int y = 10; 
    private JFrame frame; 
    private JLabel label; 
    private mypanel panel; 
    private JButton b1; 
    private JButton b2; 

    public static void main(String[] args) { 
     dabble dab = new dabble(); 
     dab.start(); 
    } 

    void start() { 
     frame = new JFrame(); 
     label = new JLabel(); 
     panel = new mypanel(); 
     b1 = new JButton("Start"); 
     b2 = new JButton("Stop"); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     b1.addActionListener(new al1()); 
     b2.addActionListener(new al2()); 

     frame.getContentPane().add(BorderLayout.NORTH, b1); 
     frame.getContentPane().add(BorderLayout.SOUTH, b2); 
     frame.getContentPane().add(BorderLayout.CENTER, panel); 
     frame.getContentPane().add(BorderLayout.EAST, label); 
     frame.setSize(600, 600); 
     frame.setVisible(true); 
    } 

    void go() { 
     new Animation().start(); 
    } 

    class al1 implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent event) { 
      go(); 
     } 
    } 

    class al2 implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent event) { 
      z = false; 
     } 
    } 

    class mypanel extends JPanel { 
     @Override 
     public void paintComponent(Graphics g) { 
      g.setColor(Color.white); 
      g.fillRect(0, 0, this.getWidth(), this.getHeight()); 
      int red = (int) (Math.random() * 255); 
      int green = (int) (Math.random() * 255); 
      int blue = (int) (Math.random() * 255); 
      Color c1 = new Color(red, green, blue); 
      g.setColor(c1); 
      g.fillOval(x, y, 20, 20); 
     } 
    } 

    class Animation extends Thread { 

     private long start; 

     @Override 
     public void run() { 
      start = System.currentTimeMillis(); 
      while (true) { 
       if (!z) { 
        return; 
       } 
       double progress = (double) (System.currentTimeMillis() - start)/ANIMATION_DURATION; 
       System.err.println(progress); 
       if (incrementing) { 
        y = (int) (10 + 500 * progress); 
       } else { 
        y = (int) (510 - 500 * progress); 
       } 
       if (progress > 1.0) { 
        start = System.currentTimeMillis(); 
        incrementing = !incrementing; 
       } 

       panel.repaint(); 
       try { 
        Thread.sleep(1000/REFRESH_RATE); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 
+0

私はそれを5回だけ実行していることに同意しますが、それらの5つの位置を表示する必要があります。それは最終的な位置だけを示しています。 –

+0

さて、repaint()を呼び出すのは、基本的にはRepaintEventリクエストをAWT-Eventキューに入れます。これは、現在のスレッドを解放すると完了します。代わりに、イベントがディスパッチされないようにAWT-Eventキューでsleepを呼び出します(repaintイベントを含む)。そのため、ループの最後に発生する単一の再描画(再描画イベントがマージされます)があります。代わりに、SwingUtilities.invokeLater(new Runnable(){public void run(){repaint();}});を呼び出す別の 'Thread'を用意してから、500 msをスリープさせる必要があります。 –

+1

実際、それが別のスレッドにある場合は、 'repaint()'を直接呼び出すことができます(これは、EDT以外の使用で安全なSwingメソッドの1つです)。 –

2

repaint()を呼び出すと、実際にパネルをペイントしない - それだけで、後に塗装されるように、それをマークします。ペイントは、イベントリスナー通知と同様に、イベントディスパッチスレッドで常に発生します。

go()が(ボタンアクションリスナーによって)イベントディスパッチスレッドで呼び出されているため、go()が実行中にパネルを再描画できません。 go()が完了するとただちに起こる1回の再描画をキューに入れるだけです。

おそらく、500msごとに1回発生するjavax.swing.Timerを使用して、ボールを1ステップ移動してからrepaint()と呼ぶことをお勧めします。

関連する問題