2016-01-19 14 views
5

私はTimerの前に私の問題はおそらく愚かなものです。私のプログラムは赤色の円を描き、無限秒後に円が緑色に変わるはずです。私はちょうどあなたがコードで見ることができるようにスイングタイマーを作った。そして、actionPerformed()メソッドを入力しますが、色は変わりません。どうにか色を変えることで私の問題を解決できますか?スイングタイマーのペインティングが動作しません

マイコード:

package igrica; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Random; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 


public class ChangingCircle implements ActionListener{ 

JFrame frame; 

Timer timer; 
Random r; 

public static void main(String[] args) { 
    ChangingCircle gui = new ChangingCircle(); 
    gui.go(); 
} 

public void go() { 
    frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    MyPanel panel = new MyPanel(); 

    frame.getContentPane().add(BorderLayout.CENTER, panel); 
    frame.setSize(300, 300); 
    frame.setVisible(true); 
} 

public void actionPerformed(ActionEvent event) { 
    frame.repaint(); 
} 

class MyPanel extends JPanel { 
    public void paintComponent(Graphics g) { 


     g.setColor(Color.red); 
     g.fillOval(100, 100, 100, 100); 

     Random r = new Random(); 

     Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() { 
      public void actionPerformed(ActionEvent ev) { 
       System.out.println("Timer out"); 
       g.setColor(Color.green); 
       g.fillOval(100, 100, 100, 100); 
      } 
     }); 
     timer.start(); 
    } 
} 
} 
+0

英語のヒント:「So」ですべての文章を開始しないでください。あなたは話をしていません。 – user1803551

+0

私は知っているべきではないが、私はどの単語が文章を始めるか分からない。 xD –

+0

"So"を削除するだけで、文章はそのままです。 – user1803551

答えて

8

コードにかなり混乱があります。これを試してみてください:

public class ChangingCircle { 

    Color color = Color.RED; 
    MyPanel panel = new MyPanel(); 

    public static void main(String[] args) { 

     SwingUtilities.invokeLater(() -> { 
      ChangingCircle gui = new ChangingCircle(); 
      gui.go(); 
     }); 
    } 

    public void go() { 

     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     frame.getContentPane().add(panel, BorderLayout.CENTER); 
     frame.pack(); 
     frame.setVisible(true); 

     Random r = new Random(); 
     Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() { 

      public void actionPerformed(ActionEvent ev) { 

       System.out.println("Timer"); 
       color = Color.GREEN; 
       panel.repaint(); 
      } 
     }); 
     timer.setRepeats(false); 
     timer.start(); 
    } 

    class MyPanel extends JPanel { 

     private int size = 100, loc = 100; 

     @Override 
     public void paintComponent(Graphics g) { 

      super.paintComponent(g); 
      g.setColor(color); 
      g.fillOval(loc, loc, size, size); 
     } 

     @Override 
     public Dimension getPreferredSize() { 

      return new Dimension(size + loc, size + loc); 
     } 
    } 
} 

アイデアはタイマーのみ描画される図形のプロパティを変更し、変更を反映するためにrepaint()を呼び出すことです。 paintComponentは、必要なときはいつでもすぐに連続して呼び出され、すぐに戻る必要があります。

具体的な注意事項:

  • Start Swing from the EDT
  • paintComponentの外部からタイマーを作成して開始するのは何度も呼び出され、多くのタイマーを作成して開始するためです。
  • タイマーを繰り返し設定しないでください。
  • paintComponentの中で最初にsuper.paintComponent(g);と呼んでください。
  • 何もしないActionListenerがあるようです。

一般的なヒント:該当

  • @Override注釈を使用してください。
  • フレームのサイズを手動で設定する代わりにpack()と呼び出し、塗装するコンポーネントの@OverridegetPreferredSizeメソッドを呼び出します。描画する内容に基づいて意味のあるサイズを返します。
  • add(component, location)を使用してください。他の方法では使用できません(廃止予定)。
  • ローカル変数ではフィールドを使用しないでください(たとえば、Random r)。
  • 大文字の定数名(Color.redではなくColor.RED)を使用してください。
+0

ありがとうございました! –

6

paintComponentメソッド内からタイマーを起動したりしないでください。このメソッドは、ペイントとペイントのみに使用する必要があります。 TimerのactionPerromed内でTimerを起動し、repaint()を呼び出して、クラスのフィールドの状態を変更し、paintComponent内のその情報を使用してそのフィールドを使用して新しい情報を描画します。

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Random; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 

public class ChangingCircle { 
    JFrame frame; 

    public static void main(String[] args) { 
     ChangingCircle gui = new ChangingCircle(); 
     gui.go(); 
    } 

    public void go() { 
     frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     MyPanel panel = new MyPanel(); 

     frame.getContentPane().add(BorderLayout.CENTER, panel); 
     frame.setSize(300, 300); 
     frame.setVisible(true); 
    } 

    public void actionPerformed(ActionEvent event) { 
     frame.repaint(); 
    } 

    class MyPanel extends JPanel { 
     private Random r = new Random(); 
     private boolean draw = false; 

     public MyPanel() { 
      Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() { 
       public void actionPerformed(ActionEvent ev) { 
        draw = true; 
        repaint(); 
       } 
      }); 
      timer.setRepeats(false); 
      timer.start(); 
     } 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (draw) { 
       g.setColor(Color.red); 
       g.fillOval(100, 100, 100, 100); 
      } 
     } 
    } 
} 

また、オーバーライド内からsuperのpaintComponentメソッドを呼び出すことを忘れないでください。

色を変更する必要がある場合は、JPanelに「color」という名前の「Color」フィールドを与え、その値をTimerから変更してからrepaint()に電話してください。再びpaintComponent内で、そのフィールドの値を使用して楕円を描画します。この状況でも、タイマーを繰り返す必要がありますので、その状況でtimer.setRepeats(false)を取り除いてください。

+0

しかし、いつも元から色を変える必要がある場合はどうすればいいですか?赤から緑、そして緑から赤まで、それはうまくいくのでしょうか? –

+0

@DomagojSabolic:TimerでColorフィールドの状態を変更し、paintComponentメソッドでそれを使用します。 –

+0

@DomagojSabolic:回答を編集してください。 –

0

タイマーは非同期で動作し、paintComponentはタイマーの処理を終了する前に終了します。

+0

しかし、私のSystem.out.printlnが動作し、タイマーが終了するたびにこのメッセージが表示されます。 –

+0

このサンプルでは、​​JFrameとJpanelがあります。多くのコンポーネントを追加すると、この実装は例外をスローします同時に、別のコンポーネントがgの同じインスタンスを使用して再ペイントします –

+0

これがどのように質問に答えるかわかりません。 'paintComponent' *は、タイマーが開始されるか、そのアクションを実行する前に終了しなければなりません。非同期の問題は無関係です。 – user1803551

関連する問題