开发者

Repainting a JPanel inside a frame

I have a JPanel inside a frame. The contents of the JPanel are supposed to be updated with each call to paintComponent (which is called by repaint()), but when I do it as below, I just see a white window. (Please excuse the mangled indentation, Eclipse does all kinds of weird stuff with tabs.)

private static void handleGUI() 
{       
    JFrame frame = new JFrame("Animation");
    frame.setPreferredSize(new Dimension(100, 100));

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Board b = new Board();

    frame.getContentPane().add(b);

    frame.开发者_运维技巧pack();
    frame.setVisible(true);

    while(true)
    {
        System.out.println("Repainting panel");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        b.repaint();
    }
}

public class Board extends JPanel
{
public Board() { t=0; }

    private int t;

public void paintComponent(Graphics g) 
{
    super.paintComponent(g);

    ++t;

    /* Variables snipped */

    g.setColor(Color.white);
    g.drawOval(0, 0, width, height);

    BufferedImage image = ImageIO.read(new File(imagePath));
    g.drawImage(image, x(t), y(t));
    /* There's some more image and rectangle drawing ahead */
}

}


You have several problems with your code, one has been mentioned above (1+ rep -- though it looks to me as if you have code now in your paintComponent method that does do drawing), your paintComponent method is flawed, but not only that, you've got a while(true) loop and a Thread.sleep in the Swing main thread, the EDT, which will put Swing and your whole GUI to sleep. Better to use a Swing Timer instead. Also, you state,

The contents of the JPanel are supposed to be updated with each call to paintComponent (which is called by repaint()),

Are you sure that you want to put program logic inside of the paintComponent method? This is usually frowned upon since you the programmer do not have complete control regarding when this method is called. It may be called when you call repaint (but not always), and may be called due to messages from the OS when you don't expect it to be called.

Also, you never want to read a file inside of the paintComponent method as this will slow your painting to a cawl.

I'd recommend these changes:

1) Create a Swing Timer with a period of 1000, and in its ActionListener's actionPerformed method, read in your image (preferably in a background thread if the image has any significant size) and have the image read into a class field, say called image.

2) In the same Timer's actionPerformed method, increment t.

3) After the image has been read in, call repaint on the drawing JPanel and have the drawing JPanel use the image variable to paint the image with. Be careful if you are using a background thread to read in the image as you'll need to have this thread notify the GUI when the image has been completely read in. If using a SwingWorker to do this, you can add a PropertyChangeListener that listens to the SwingWorker's state value and triggers when this changes to StateValue.DONE.

If any of this is unclear or confusing, please ask for clarification.

edit: if the images aren't too big, you may wish to read them all in at one time, or do a batch read when a bunch are needed. There's no absolute need to read in the images immediately before using them.


Don't make the thread sleep. Use a Swing Timer to set off the repaint events.


your paintComponent just calls super.paintComponent. So the JPanel while paint it self, which will be light gray, or white or light brown or something depending on your look and feel.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜