有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

swing动画:移动时隐藏的对象(JAVA、图形、动画)

我正在绘制一个图,其中一个圆圈沿着一条线移动,并在路径的3个点停留几秒钟。 我已经设法做到了,但是,它不显示圆圈移动,它只显示当圆圈停止。。。 我不明白为什么

非常感谢你的帮助

这是我的密码:

public class Robot0 extends JFrame implements ActionListener {

    public Robot0(String nom, int larg, int haut) {
        setTitle(nom); 
        setSize(larg, haut); 
        setLocationRelativeTo(null); 
        setResizable(false); 
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                     
        setVisible(true); 
    }

    Timer tm = new Timer(10, this);

    private int posX = 0; 
    private int posY = 0;
    private int velX = 1;

    public int getPosX() {
        return posX;
    }

    public void setPosX(int posX) {
        this.posX = posX;
    }

    public int getPosY() {
        return posY;
    }

    public void setPosY(int posY) {
        this.posY = posY;
    }

    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(Color.BLACK);
        // Draw the pathway 
        int xt[] = { 50, 50, 250, 250, 350, 350 };
        int yt[] = { 50, 150, 150, 50, 50, 150 };
        g.drawPolyline(xt, yt, 6);

        // On the pathway, draw 3 squares (the 3 rooms)
        g.setColor(Color.GREEN);
        g.drawRect(35, 135, 30, 30);
        g.drawRect(235, 35, 30, 30);
        g.drawRect(335, 135, 30, 30);

        g.setColor(Color.WHITE);
        g.fillOval(40 + posX, 40 + posY, 20, 20);

        g.setColor(Color.RED);
        g.drawLine(45 + posX, 50 + posY, 55 + posX, 50 + posY);
        g.drawLine(50 + posX, 45 + posY, 50 + posX, 55 + posY);

        tm.start();
    }

    int segment = 0;

    public void actionPerformed(ActionEvent e) {

        // move along the 1st segment
        if (posY < 100 && segment == 0) {
            setPosY(posY + velX);
        }

        if (posY == 100 && posX == 0) {
            segment = 1;
            try {
                Thread.sleep(15000);
            } catch (InterruptedException ex) {
                Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        // move along the second segment
        if (posX <= 200 && segment == 1) {
            setPosX(posX + velX);
        }

        if (posX == 200 && posY == 100) {
            segment = 2;
        }

        // move along the third segment
        if (posY > 0 && segment == 2) {
            setPosY(posY - velX);
        }

        if (posX == 200 && posY == 0) {
            segment = 3;
            try {
                Thread.sleep(15000);
            } catch (InterruptedException ex) {
                Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        // move along the fourth segment
        if (posX < 300 && segment == 3) {
            setPosX(posX + velX);
        }

        if (posX == 300 && posY == 0) {
            segment = 4;
        }

        // move along the fifth segment
        if (posY < 100 && segment == 4) {
            setPosY(posY + velX);
        }

        if (posX == 300 && posY == 100) {
            segment = 6;
            try {
                Thread.sleep(15000);
            } catch (InterruptedException ex) {
                Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        repaint();
    }

// Build the Panel
    public static void main(String[] args) {
        Robot0 r = new Robot0("Robot0", 800, 600);
    }

}

共 (1) 个答案

  1. # 1 楼答案

    Swing是一个单线程库。所有绘制任务都在事件调度器线程中执行 (EDT
    正如安德鲁·汤普森(Andrew Thompson)所评论的,在EDT上运行长进程(如睡眠)会使该线程保持忙碌,因此它不会做其他事情 比如更新gui
    gui变得无响应(冻结)。 因此,首先要做的是消除所有的睡眠
    要在每一站停车,请使用第二个计时器:

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class Robot0 extends JFrame implements ActionListener {
    
        private static final int PARKING_TIME = 15000;
        Timer moveTimer , waitTimer;
        private boolean isParking = false;
    
        public Robot0(String nom, int larg, int haut) {
            moveTimer = new Timer(10, this);
            waitTimer = new Timer(PARKING_TIME, e-> isParking = false);
            waitTimer.setRepeats(false);
    
            setTitle(nom);
            setSize(larg, haut);
            setLocationRelativeTo(null);
            setResizable(false);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setVisible(true);
        }
    
        private int posX = 0;
        private int posY = 0;
        private final int velX = 1;
    
        public int getPosX() {
            return posX;
        }
    
        public void setPosX(int posX) {
            this.posX = posX;
        }
    
        public int getPosY() {
            return posY;
        }
    
        public void setPosY(int posY) {
            this.posY = posY;
        }
    
        @Override
        public void paint(Graphics g) {
            super.paint(g);
            g.setColor(Color.BLACK);
            // Draw the pathway
            int xt[] = { 50, 50, 250, 250, 350, 350 };
            int yt[] = { 50, 150, 150, 50, 50, 150 };
            g.drawPolyline(xt, yt, 6);
    
            // On the pathway, draw 3 squares (the 3 rooms)
            g.setColor(Color.GREEN);
            g.drawRect(35, 135, 30, 30);
            g.drawRect(235, 35, 30, 30);
            g.drawRect(335, 135, 30, 30);
    
            g.setColor(Color.WHITE);
            g.fillOval(40 + posX, 40 + posY, 20, 20);
    
            g.setColor(Color.RED);
            g.drawLine(45 + posX, 50 + posY, 55 + posX, 50 + posY);
            g.drawLine(50 + posX, 45 + posY, 50 + posX, 55 + posY);
    
            moveTimer.start();
        }
    
        int segment = 0;
    
        @Override
        public void actionPerformed(ActionEvent e) {
    
            if(isParking) return; //execute only when not parking 
    
            // move along the 1st segment
            if (posY < 100 && segment == 0) {
                setPosY(posY + velX);
            }
    
            if (posY == 100 && posX == 0 && segment != 1) { //!=1 so it will not be invoked again 
                segment = 1;
                isParking = true; //flag that robot is parking 
                waitTimer.start();
                return;
            }
    
            // move along the second segment
            if (posX <= 200 && segment == 1) {
                setPosX(posX + velX);
            }
    
            if (posX == 200 && posY == 100) {
                segment = 2;
            }
    
            // move along the third segment
            if (posY > 0 && segment == 2) {
                setPosY(posY - velX);
            }
    
            if (posX == 200 && posY == 0 && segment !=3) {
                segment = 3;
                isParking = true;
                waitTimer.start();
                return;
            }
    
            // move along the fourth segment
            if (posX < 300 && segment == 3) {
                setPosX(posX + velX);
            }
    
            if (posX == 300 && posY == 0) {
                segment = 4;
            }
    
            // move along the fifth segment
            if (posY < 100 && segment == 4) {
                setPosY(posY + velX);
            }
    
            if (posX == 300 && posY == 100 && segment !=6) {
                segment = 6;
                isParking = true;
                waitTimer.start();
                return;
            }
            repaint();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(()->new Robot0("Robot0", 800, 600));
        }
    }
    

    待办事项:

    1. 在JPanel上实现自定义绘制
    2. 简化actionPerformed 逻辑

    编辑:以下是一个实施方案,其中有一些改进不一定与所问问题有关:

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class Robot0 extends JFrame {
    
        public Robot0(String nom) {
            setTitle(nom);
            setLocationRelativeTo(null);
            setResizable(false);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            add(new Floor());
            pack();
            setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(()->new Robot0("Robot0"));
        }
    }
    
    class Floor extends JPanel implements ActionListener{
    
        private static final int PARKING_TIME = 5000, REPAINT_TIME = 10, W = 400, H = 200;
        private static final int ROOM_SIZE = 30, ROBOT_SIZE = 20, CROSS_SIZE = 10;
    
        private final Timer moveTimer , waitTimer;
        private boolean isParking = false;
    
        private int posX = 0, posY = 0;
        private final int velX = 1;
    
        // pathway
        private static final int PATH_X[] = { 50,  50, 250, 250, 350,  350 };
        private static final int PATH_Y[] = { 50, 150, 150,  50,  50,  150 };
        //rooms
        private static final Point[] ROOM_CENTERS = {new Point(PATH_X[1],PATH_Y[1]),
                                                     new Point(PATH_X[3],PATH_Y[3]),
                                                     new Point(PATH_X[5],PATH_Y[5]) };
    
        Floor() {
            moveTimer = new Timer(REPAINT_TIME, this);
            waitTimer = new Timer(PARKING_TIME, e-> isParking = false);
            waitTimer.setRepeats(false);
            posX = PATH_X[0]; posY = PATH_Y[0];
            setPreferredSize(new Dimension(W, H));
            moveTimer.start(); //no need to restart with every paint
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.BLACK);
    
            g.drawPolyline(PATH_X, PATH_Y, 6);
    
            // draw rooms
            g.setColor(Color.GREEN);
            for(Point center : ROOM_CENTERS){
                drawSquareAround(center, g);
            }
    
            //robot
            g.setColor(Color.WHITE);
            g.fillOval( posX - ROBOT_SIZE/2 , posY - ROBOT_SIZE/2 , ROBOT_SIZE, ROBOT_SIZE);
    
            //cross
            g.setColor(Color.RED);
            g.drawLine(posX - CROSS_SIZE/2, posY, posX + CROSS_SIZE/2, posY);
            g.drawLine(posX, posY - CROSS_SIZE/2, posX,  posY + CROSS_SIZE/2);
        }
    
    
        private void drawSquareAround(Point center, Graphics g) {
            g.drawRect(center.x - ROOM_SIZE/2, center.y - ROOM_SIZE/2, ROOM_SIZE, ROOM_SIZE);
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
    
            if(isParking) return; //execute only when not parking
    
            if (posX <= PATH_X[0]  &&  posY < PATH_Y[1]) {// move along the 1st segment
                setPosY(posY + velX);
            }else if (posX < PATH_X[2] && posY == PATH_Y[1]) { //move along the second segment
                setPosX(posX + velX);
            }else  if (posX == PATH_X[2] && posY > PATH_Y[3]) { //move along the third segment
                setPosY(posY - velX);
            }else if (posY == PATH_Y[3] && posX < PATH_X[4]) {// move along the fourth segment
                    setPosX(posX + velX);
            }else if (posX == PATH_X[4] && posY < PATH_Y[5]){// move along the fifth segment
                setPosY(posY + velX);
            }else {
                moveTimer.stop(); //move finished, stop repainting
                return;
            }
    
            //park if at room center
            if(isRoomCeter()){
                park();
            }
            repaint();
        }
    
        private void park() {
          isParking = true; //flag that robot is parking
          waitTimer.start();
        }
    
        private boolean isRoomCeter() {
            for (Point center : ROOM_CENTERS){
                if(posX == center.x && posY == center.y) return true;
            }
            return false;
        }
    
        public int getPosX() {
            return posX;
        }
    
        public void setPosX(int posX) {
            this.posX = posX;
        }
    
        public int getPosY() {
            return posY;
        }
    
        public void setPosY(int posY) {
            this.posY = posY;
        }
    }