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

Java 使用鼠标事件时,JPanel重新绘制不可见,java,swing,jpanel,mouseevent,repaint,Java,Swing,Jpanel,Mouseevent,Repaint,我试图创建一个简单的动画:在面板内移动一个椭圆形。我做到了。它进展顺利。但当我尝试向帧添加按钮并使用MouseeEvent触发此动画时,动画冻结。我看到第一个椭圆形,然后经过一段确定的时间,最后一个椭圆形。这个时间可能是移动所需的净时间(根据我的方法中给定的睡眠时间计算)。我已将事件更改为MouseClick/MousePress和所有其他事件,但情况相同。如果我注释与侦听器相关的代码并从main方法运行我的“animate()”方法,动画工作正常。提前谢谢 import javax.swing

我试图创建一个简单的动画:在面板内移动一个椭圆形。我做到了。它进展顺利。但当我尝试向帧添加按钮并使用MouseeEvent触发此动画时,动画冻结。我看到第一个椭圆形,然后经过一段确定的时间,最后一个椭圆形。这个时间可能是移动所需的净时间(根据我的方法中给定的睡眠时间计算)。我已将事件更改为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();
        }
    }
}
import javax.swing.*;
导入java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseListener;
/*这是我的主课*/
课堂好奇心{
公共静态void main(字符串[]args){
//实例化MyFrames,带有Frame和Panel的类
MyFrames MyFrames=新的MyFrames();
myFrames.frameSetup();
}
}
类MyFrames{
JFrame-myFrame;
按钮;
/*******创建JPanel子类******
*我正在这个面板上绘制动画
*****************************************/
@抑制警告(“串行”)
类MyPanel扩展了JPanel{
@凌驾
公共组件(图形g){
g、 fillRect(0,0,this.getWidth(),this.getWidth());
g、 setColor(颜色为黄色);
g、 fillOval(animationObjectX,animationObjectY,30,30);
myFrame.setVisible(true);
}
}
//创建对面板的引用
我的小组我的小组;
/*******一个用于在按钮上侦听鼠标事件的类**********
************************************************************/
类ButtonListener实现MouseListener{
@凌驾
公共无效mouseClicked(MouseEvent e){
//调用动画方法
制作动画();
}
公共无效mouseenterned(MouseEvent e){}
公共无效mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){}
公共无效MouseEvent e{}
}
//事件侦听器类引用
按钮列表器bl;
/******************************
*MyFrame类构造函数
*****************************/
MyFrames(){
myFrame=新JFrame(“我的应用程序”);
按钮=新按钮(“按下移动”);
myPanel=新的myPanel();
bl=新按钮列表();
}
/**************************************************
**我的动画对象的坐标(此处为椭圆形)
**我增加这些以创建动画效果
*************************************************/
int-animationObjectX;
int动画对象;
void frameSetup(){
/************************************
//配置帧
*************************************/
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setSize(600300);
myFrame.setLocation(200200);
myFrame.setVisible(true);
/************************************
//将面板添加到框架
*************************************/
myFrame.getContentPane().add(BorderLayout.CENTER,myPanel);
myFrame.getContentPane().add(BorderLayout.SOUTH,按钮);
//将鼠标侦听器添加到按钮
按钮。添加鼠标侦听器(bl);
}
/*********动画方法***********
*只是改变坐标和重新油漆
******************************************/
void animate(){

对于(int x=0;x您正在阻止事件分派线程。
repaint()
仅标记要重绘的组件,Swing没有机会在动画循环中实际绘制它。请改用Swing计时器。 见:

如果没有从侦听器中调用它,则它可以工作,因为您的main在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();
        }
    });
}

我不知道你的问题是什么,但我注意到了一些事情。首先,在
paintComponent()
中,你调用的是
myFrame.setVisible(true);
,这在每次绘制时都不是必需的。像在构造函数中一样,执行一次。同样,在相同的方法中,你调用
setColor()
设置为黄色,您在哪里设置背景色?据我所见,背景和椭圆形都是相同的颜色。设置可见(true)是我在将问题发布到这里之前忘记删除的内容。我在尝试了所有我知道的东西后才将其删除。这只是在事情不起作用后的一次疯狂尝试。请忽略它。关于背景:当从main()调用animate()方法时,动画如何工作。当我添加MouseeEvent处理程序时,问题就出现了…感谢您的关注。感谢您的回答,您一定从我的代码中得出结论,我是新手。感谢您的提示,我理解线程/事件调度。尽管我还没有完全理解您的解决方案(我的错),它是连贯的,我可以看到我的错误。我正在处理它,并将在下一次编辑+1中为Swing Timer advice发布解决方案:-)@AnuragPriyadarshi:另一个变体是,尽管这种方法会带来一些影响。这里可以看到一个小的影响。在动画结束之前,它不会阻止按钮,从而可以同时启动多个动画。有没有办法阻止整个GUI(有很多面板和小部件)在动画结束之前?@MarkJeronimus您可以对要在动画期间禁用(并在完成后重新启用)的UI部分调用
setEnabled(false)
。禁用窗口将禁用与子组件的所有交互,但