动画:移动时隐藏的对象(JAVA、图形、动画)
Animation: objects hidden while moving (JAVA, GRAPHICS, ANIMATION)
我正在构建一个图表,其中有一个圆圈沿着一条线移动,并在路径的 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);
}
}
Swing 是一个单线程库。所有的绘画任务都在Event Dispatcher Thread中执行
(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));
}
}
待办事项:
- 在JPanel 上实现自定义绘画。
- 简化
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;
}
}
我正在构建一个图表,其中有一个圆圈沿着一条线移动,并在路径的 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);
}
}
Swing 是一个单线程库。所有的绘画任务都在Event Dispatcher Thread中执行
(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));
}
}
待办事项:
- 在JPanel 上实现自定义绘画。
- 简化
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;
}
}