2

I have a JFrame , which has a JPanel and a JButton . The JFrame is set to BorderLayout , and i expected my code to repaint the panel every 500 millisecs after the button has been clicked. But even though the setup goes into a loop , the frame does not repaint.

Here is what i wrote for when the button is clicked

public void actionPerformed(ActionEvent e) {
    while(true){
        try {
            frame.repaint(); // does not repaint
            Thread.sleep(500);
        } catch (InterruptedException exp) {
            exp.printStackTrace();
        }
    }
}

and this for the setup :

public void go() {
    b.addActionListener(new ButtonListener()); // b is the JButton
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // frame is the JFrame
    frame.setLayout(new BorderLayout());
    frame.add(BorderLayout.CENTER, p); // p is a MyPanel
    frame.add(BorderLayout.SOUTH, b);
    frame.setSize(300, 300);
    frame.setVisible(true);

}

class MyPanel extends JPanel { // p is an instance of this MyPanel class

    public void paintComponent(Graphics gr) {
        gr.fillRect(0, 0, this.getWidth(), this.getHeight());

        int r, g, b, x, y;
        r = (int) (Math.random() * 256);
        g = (int) (Math.random() * 256);
        b = (int) (Math.random() * 256);
        x = (int) (Math.random() * (this.getWidth() - 15 ));
        y = (int) (Math.random() * (this.getHeight() - 15));

        Color customColor = new Color(r, g, b);
        gr.setColor(customColor);
        gr.fillOval(x, y, 30, 30);
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Somjit
  • 2,503
  • 5
  • 33
  • 60
  • 1
    How would it paint, when the code is blocking the `Event Dispatch Thread` ? Try using [javax.swing.Timer](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html), for this purpose, instead of `Thread.sleep(...)` – nIcE cOw Oct 07 '13 at 15:27
  • 4
    well , if i knew that i wouldn't be posting here would i.. but thanks for pointing things out. – Somjit Oct 07 '13 at 15:28
  • 1
    You might want to add `super.paintComponent(gr);` at the top of `MyPanel#paintComponent(Graphics)`. I've missed that quite often, wondering why nothing was drawn. – 11684 Oct 07 '13 at 15:31
  • Try this [example](http://stackoverflow.com/a/10536134/1057230) and [another example](http://stackoverflow.com/a/13795187/1057230) +1 to the question, though I was writing my comment, and suddenly my internet went down. But for the rest you're MOST WELCOME and KEEP SMILING :-) – nIcE cOw Oct 07 '13 at 15:32
  • that's some commitment to a tagline you have there ! anyways , thanks for the link too :) – Somjit Oct 07 '13 at 15:54

2 Answers2

3

Your ActionListener contains 2 surefire mechanisms for blocking a Swing Application - an infinite loop and a Thread.sleep call. Use a Swing Timer instead

Timer timer = new Timer(500, new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        frame.repaint();
    }
});
timer.setRepeats(false);
timer.start();
Reimeus
  • 158,255
  • 15
  • 216
  • 276
3

Code executed from a listener executes on the Event Dispatch Thread (EDT) and the Thread.sleep() is causing the EDT to sleep so the GUI can never repaint itself. Don't use Thread.sleep.().

Instead use a Swing Timer.

camickr
  • 321,443
  • 19
  • 166
  • 288