使用鼠标事件时,JPanel重绘不可见

时间:2013-06-11 19:49:09

标签: java swing jpanel mouseevent repaint

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

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();
        }
    }
}

1 个答案:

答案 0 :(得分:2)

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

如果没有从侦听器调用它,那么它可以工作,因为你的主要是在不运行 - 应该,因为在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();
        }
    });
}