2013-06-11 27 views
1

我试图创建一个简单的动画:在Panel中移动一个椭圆。我做的。它移动顺利。但是,当我尝试向框架添加按钮并使用MouseEvent触发此动画时,动画会冻结。我看到了第一个椭圆形,然后经过了一定的时间后,最后一个椭圆形。这一次可能是需要跨越的净时间(根据我方法中的给定睡眠时间计算)。我已将事件更改为MouseClick/MousePress和所有其他人,但情况相同。如果我评论与侦听器相关的代码并从主方法运行我的“animate()”方法,动画工作正常。提前致谢。使用鼠标事件时,JPanel重绘不可见

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 

/*This is my main Class*/ 
class Curiosity{ 
    public static void main(String [] args) { 
     //Instantiating MyFrames, the class with Frame and Panel 
     MyFrames myFrames = new MyFrames(); 
     myFrames.frameSetup(); 
    } 
} 

class MyFrames{ 
    JFrame myFrame ; 
    JButton button ; 
    /*******Creating A JPanel Child Class****** 
    * I am drawing the animation on this panel 
    *****************************************/ 
    @SuppressWarnings("serial") 
    class MyPanel extends JPanel { 
     @Override 
     public void paintComponent(Graphics g){ 
      g.fillRect(0, 0, this.getWidth(), this.getWidth()); 
      g.setColor(Color.yellow); 
      g.fillOval(animationObjectX, animationObjectY, 30, 30); 
      myFrame.setVisible(true); 
     } 
    } 
    //creating reference to Panel 
    MyPanel myPanel ; 

    /******* A class to listen to mouse event on button********** 
    ************************************************************/ 
    class ButtonListener implements MouseListener{ 
     @Override 
     public void mouseClicked(MouseEvent e) { 
      //calling the animation method 
      animate(); 
     } 
     public void mouseEntered(MouseEvent e) {} 
     public void mouseExited(MouseEvent e) {} 
     public void mousePressed(MouseEvent e) {} 
     public void mouseReleased(MouseEvent e) {} 
    } 
    //Event Listener Class Reference 
    ButtonListener bl; 

    /****************************** 
    * MyFrame Class Constructor 
    *****************************/ 
    MyFrames(){ 
    myFrame = new JFrame("my App"); 
    button = new JButton("press to move"); 
    myPanel = new MyPanel(); 
    bl= new ButtonListener(); 

    } 
    /************************************************** 
    ** coordinates for my animation object (here an oval) 
    ** I increment these to create animation effect 
    *************************************************/ 
    int animationObjectX; 
    int animationObjectY; 

    void frameSetup(){ 
     /************************************ 
     //Configuring Frame 
     *************************************/ 
     myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     myFrame.setSize(600,300); 
     myFrame.setLocation(200,200); 
     myFrame.setVisible(true); 
     /************************************ 
     //Adding panel to Frame 
     *************************************/ 
     myFrame.getContentPane().add(BorderLayout.CENTER,myPanel); 
     myFrame.getContentPane().add(BorderLayout.SOUTH, button); 
     //adding mouse listener to button 
     button.addMouseListener(bl); 

    } 
    /********* the animation method *********** 
    * just changing coordinates and repainting 
    ******************************************/ 
    void animate() { 
     for(int x = 0;x<100;x++){ 
      animationObjectX=x; 
      animationObjectY=x; 
      try {Thread.sleep(15);} catch (InterruptedException e){} 
      myFrame.repaint(); 
     } 
    } 
} 
+0

我不知道你的问题是什么,但我注意到了一些事情。首先,在你的'paintComponent()'中,调用'myFrame.setVisible(true);',每次绘制都不需要。做一次,就像在构造函数中一样。同样的方法,你调用'setColor()'为黄色,你在哪里设置背景颜色?从我所看到的背景和椭圆都是相同的颜色。 – Frecklefoot

+0

setVisible(true)是我在发布我的问题之前忘记删除的内容。当我尝试了我所知道的一切时,我已经说出了它。事情没有奏效后,这只是一个狂野的努力。请忽略它。关于背景:当从main()调用animate()方法时,动画如何工作。当我添加MouseEvent处理程序时发生问题...感谢您无论如何查看它。 –

回答

2

您正在阻止事件分派线程。 repaint()只标记重绘的组件,而Swing没有机会在您的动画循环中实际绘制它。改用摇摆计时器。 请参阅:http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html

它的工作原理,如果它不从听者称呼,是因为你的主要是在EDT运行 - 它应该,因为初始化EDT以外的Swing组件是不安全的。你应该改变代码为

public static void main(String [] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      //Instantiating MyFrames, the class with Frame and Panel 
      MyFrames myFrames = new MyFrames(); 
      myFrames.frameSetup(); 
     } 
    }); 
} 
+0

感谢您的回答,您必须从我的代码中得出结论,我是新手。感谢你的线索,我了解线索/事件派遣。虽然我没有完全理解你的解决方案(我的不好),但它是连贯的,我可以看到我的错误。我正在处理它,并将在下次编辑 –

+0

+1中发布解决方案以用于Swing Timer建议:-) @AnuragPriyadarshi:另一个变体是[JCompnent.paintImmediately(...)](http://docs.oracle.com/ javase/7/docs/api/javax/swing/JComponent.html#paintImmediately(int,%20int,%20int,%20int)),尽管这种方法会带来一些影响。一个小的[示例](http://stackoverflow.com/a/10352884/1057230)可以在这里看到。 –

+0

这不会阻止按钮,直到动画结束,可以启动多个同时动画。有没有办法阻止整个GUI(有很多面板和小部件),直到动画结束? –