为什么重绘()并不总是有效?

时间:2015-03-11 17:02:27

标签: java swing repaint

在我的第一个程序重绘工作正常,但在第二个程序中我有一个问题。

    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;

    public class repaint1 {

        public static void main(String[] args) {
            JFrame win = new JFrame("");
            test1 content = new test1();
            win.setContentPane(content);
            win.setSize(600, 400);
            win.setLocation(100, 100);
            win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            win.setResizable(false);
            win.setVisible(true);
            content.function();

        }

    }

    class test1 extends JPanel {

        private BufferedImage img;

        public int x = 50;
        public int y = 50;

        public test1() {

        }

        public void function() {

            try {

                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }

            for (int i = 50; i < 150; i++) {
                x = i;
                y = i;

                try {

                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }

                repaint();
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            try {
                img = ImageIO.read(new File("images.jpg"));
                g.drawImage(img, x, y, null); 

            } catch (IOException ex) {
                // handle exception...
            }

        }

    }



import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class repaint2 {

    public static void main(String[] args) {

        JFrame f = new JFrame("JFrame");
        test2 content = new test2();
        f.setContentPane(content);
        f.setSize(600, 400);
        f.setLocation(100, 100);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setResizable(false);
        f.setVisible(true);

    }

}

class test2 extends JPanel {

    private BufferedImage img;

    public int x = 50;
    public int y = 50;

    public test2() {

        JButton button = new JButton("Start !");
        button.setBounds(458, 24, 122, 23);
        button.setVisible(true);
        add(button);

        button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                // Execute when button is pressed

                function();

            }

        });

    }

    public void function() {

        for (int i = 50; i < 150; i++) {

            x = i;
            y = i;

            repaint();

            try {

                Thread.sleep(10);
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }

        }
    }

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

        try {
            img = ImageIO.read(new File("images.jpg"));
            g.drawImage(img, x, y, null);

        } catch (IOException ex) {
            // handle exception...
        }

    }

}

2 个答案:

答案 0 :(得分:1)

在第一种情况下,从主线程调用function()方法,因此当您调用sleep()时,此线程会休眠,这不会影响GUI的绘制。

在第二种情况下,从ActionListener调用function()方法。从侦听器执行的所有代码都在事件调度线程(EDT)上调用,该线程负责重新绘制GUI。当你告诉Thread休眠()时,EDT会休眠,所以在循环完成执行之前它不能重新绘制GUI。

在ActionListener代码中,您需要启动一个单独的Thread。一种方法是使用SwingWorker

阅读Concurrency上的Swing教程中的部分以获取更多信息。

答案 1 :(得分:-1)

每次需要在JPanel类中使用实现Runnable时移动图像。这个类(MyJPanleClass)的行为与JPanel和Thread一样。

public class MyJPanleClass extends JPanel implements Runnable{

   public MyJPanleClass(){
      //constractor
   }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //do your staff with g
    }

    @Override
    public void run(){
       repaint();
    }

}

要从主类执行它,只需编写以下代码:

MyJPnaleClass jp=new MyJPanelClass();
Thread t1=new Thread(jp);
t1.start();//this will call run class
try{
t1.join();//running the thread until it finish. 
}catch(Exception ex){}

如果您对线程一无所知,请点击链接进行了解:Thread in java tutorial