2016-09-27 3 views
1

私は基本的なJavaをやろうとしています。これは、JComponentクラスを使用してシェイプを描画し、アニメーションは上部のボタンクリックでトリガされます。forループがエスケープされ、2つのフレームだけでエスケープされるまで、再描画は行われません。

コンポーネントコードがちょうどこのJPanelの

public void paintComponent(Graphics g){  
    Dimension dim = getSize();  
    g.setColor(Color.GREEN); 
    g.fillOval(margin, 150, 100, 100); 
    super.paintComponent(g); 
} 

に追加されるアニメーションはわずかだけ右に円を移動するように左マージンを編集することは、forループ内で行われます。

​​3210

しかし、一度に20ピクセル移動するループの最後までは移動していないようです。以前私は睡眠機能を持っていましたが、アニメートしないと無意味に思えました。

洞察?乾杯。

興味がある人のための全体のコードは、乱雑、大部分がちょうどスタイリング取得する:一時停止せずに

class Main extends JFrame{ 

public JPanel panel = new JPanel(); 
JButton button1 = new JButton("Move Right"); 

CreateComps cc = new CreateComps(); 

Main(){ 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    initUI(); 
} 

void initUI(){ 
    setSize(800,800); 
    setBackground(Color.GRAY); 
    setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); 

    JPanel topBar = new JPanel(); 
    topBar.setPreferredSize(new Dimension(800,30)); 
    topBar.setMaximumSize(new Dimension(800,30)); 
    topBar.setLayout(new BorderLayout()); 
    topBar.add(button1, BorderLayout.WEST); 
    topBar.setBackground(Color.GRAY); 

    JPanel container = new JPanel(); 
    container.setLayout(new GridBagLayout()); 
    container.setBackground(Color.DARK_GRAY); 

    panel.setPreferredSize(new Dimension(600,500)); 
    panel.setMinimumSize(new Dimension(600,500)); 
    panel.setBackground(Color.WHITE); 
    panel.setLayout(new BorderLayout()); 
    panel.add(cc, BorderLayout.CENTER); 

    add(topBar); 
    add(container); 
    container.add(panel); 

    Listener listen = new Listener(); 
    button1.addActionListener(listen); 

    setVisible(true); 
} 

public void reValidate(){ 
    panel.revalidate(); 
    panel.repaint(); 
} 

public static void main (String[] args){ 
    Main main = new Main(); 
} 

class Listener implements ActionListener{ 
    @Override 
    public void actionPerformed(ActionEvent e) { 

     System.out.println("Listening.."); 
     if(e.getSource().equals(button1)){ 
      int getMarg = cc.getMargin(); 
      for(int i = 1;i < 20;i++){ 
       getMarg = cc.getMargin(); 
       cc.setMargin(getMarg + 1);    
       reValidate(); 
       System.out.println(i); 
      } 
     }      
    } 
} 



} 

class CreateComps extends JComponent{ 

int margin = 10;   
public void setMargin(int marg){ 
    margin = marg; 
} 
public int getMargin(){ 
    return margin; 
} 
@Override 
public Dimension getPreferredSize(){ 
    return new Dimension(new Dimension(200,200)); 
} 
@Override 
public Dimension getMaximumSize(){ 
    return new Dimension(new Dimension(200,200)); 
} 
@Override 
public Dimension getMinimumSize(){ 
    return new Dimension(new Dimension(200,200)); 
} 
public void paintComponent(Graphics g){  
    Dimension dim = getSize();  
    g.setColor(Color.GREEN); 
    g.fillOval(margin, 150, 100, 100); 
    super.paintComponent(g); 
} 

}

答えて

0

を、あなたはrevalidateへの呼び出しを積み重ねていると、結果よりも他に何も表示されません最後の呼び出しの

あなたが以前に持っていたスリープ機能は、おそらくEvent Dispatch Threadで呼び出されました。これは、イベントディスパッチとGUIアップデート全体をブロックしているためです。

@Override 
public void actionPerformed(final ActionEvent e) { 

    System.out.println("Listening.."); 
    if (e.getSource().equals(button1)) { 
     new Thread() { 
      @Override 
      public void run() { 
       int getMarg = cc.getMargin(); 
       for (int i = 1; i < 20; i++) { 
        getMarg = cc.getMargin(); 
        cc.setMargin(getMarg + 1); 
        reValidate(); 
        System.out.println(i); 

        try { 
         Thread.sleep(50); 
        } catch (Throwable e) { 
        } 

       } 
      } 
     }.start(); 

    } 

} 

それとも、単にこの仕事に最適ですTimer、使用することができます:

は、いずれかの別のThreadsleep呼び出しを使用することを検討してください。

+1

ありがとう、回答としてマーク。歓声: –

+0

これは問題の核心(EDT上のタイトなループ/スリープ)を照らしているが、そのようなコードの小さな部分でこのような大量の悪い習慣があるという答えをupvoteできない。一度、Swingのほとんどすべてのクラスは 'Swingはスレッドセーフではありません。 '非EDTスレッドから 'getMargin()'や 'setMargin()'などを呼び出さないでください。そしてなぜあなたは 'Runnable'をEDT上で直接スリープの必要なしに動かすのに便利なSwing' Timer'クラスを持っているときに、新しいスレッド全体を作りますか? – Ordous

関連する問題