简体   繁体   中英

repaint() not being called properly from actionlistener

My question is about how to get repaint() to work properly when executed from a method, or more specifically from an actionlistener. To illustrate my point, the moveIt() method when executed from the initial go(), invokes repaint() as expected and you see the circle slide. When moveIt() is called from the button ActionListener, the circle jumps from start position to end position. I have included a println statement before the call to repaint() and inside the repaint() and you can see that repaint() is called 10 times at startup and only once when the button is pressed. - Thanks in advance for your assistance.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SimpleAnimation {
int x=70;
int y=70;
MyDrawPanel drawPanel;

public static void main(String[] args) {
    SimpleAnimation gui = new SimpleAnimation();
    gui.go();
}
public void go(){
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    drawPanel = new MyDrawPanel();
    JButton button = new JButton("Move It");
    frame.getContentPane().add(BorderLayout.NORTH, button);
    frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
    button.addActionListener(new ButtonListener());
    //frame.getContentPane().add(drawPanel);
    frame.setSize(300,300);
    frame.setVisible(true);
    // frame.pack();  Tried it with frame.pack with same result.
    moveIt();
}//close go()
public void moveIt(){
    for (int i=0; i<10; i++){
            x++;
            y++;
            drawPanel.revalidate();
            System.out.println("before repaint"); //for debugging
            drawPanel.repaint();            
        try{
            Thread.sleep(50);
        }catch (Exception e){}
    }
}//close moveIt()
class ButtonListener implements ActionListener{

    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub
            moveIt();   
    }
}//close inner class
class MyDrawPanel extends JPanel{
    public void paintComponent(Graphics g){
        System.out.println("in repaint"); //for debugging
        g.setColor(Color.white);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());

        g.setColor(Color.blue);
        g.fillOval(x, y, 100, 100);
    }
}//close inner class
}

You are performing a long running task (sleeping) on the EDT(Event Dispatch Thread). As a result when the EDT is sleeping it cannot update the UI and repaints do not work as expected.

To correct the situation always sleep on a seperate thread.

Use SwingWorker or Timer for such situations

Look at this post for more info about how to access swing components in a thread-safe way.

UPDATE: This page explains it better.

Calling Thread.sleep in the ActionListener blocks the EDT and causes the GUI to "freeze". You could use a Swing timer here instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM