我有一个Java swing应用程序,它使用自己实现的JPanel创建JFrame。该JPanel应该包含一个矩阵,每次更改后都应重新绘制。 该矩阵包含元素(在我的应用中为“机器人”),并在其适合的矩阵单元格中用圆圈表示。
在我的面板内部,我试图将其中一个机器人移动30次(意思是-将圆移动到矩阵中的相邻单元格),并在每次移动后重绘此矩阵。但是,当我在移动机器人后调用重绘时,paintComponent()
不会触发。我不知道应该进行哪些更改才能使其按预期工作。
在我的代码中与该问题有关的部分:
RobotsWorldSimulator
import javax.swing.*;
public class RobotsWorldSimulator {
public static int robotsWorldSize;
public static int CELL_HEIGHT = 20;
public static int CELL_WIDTH = 20;
private static RobotsWorld robotsWorld;
private static JFrame mainFrame;
public static void main(String[] args) {
inputWorldSize();
robotsWorld = new RobotsWorld(robotsWorldSize);
mainFrame = new JFrame("Robots world!");
JPanel robotsWorldPanel = new RobotsWorldPanel(robotsWorld);
mainFrame.setSize(robotsWorldPanel.getWidth() + CELL_WIDTH * 1, robotsWorldPanel.getHeight() + CELL_HEIGHT * 2);
mainFrame.add(robotsWorldPanel);
mainFrame.setVisible(true);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private static void inputWorldSize() {
boolean validWorldSize = false;
while (!validWorldSize){
// prompt the user to enter their wanted size
String worldSizeString = JOptionPane.showInputDialog(mainFrame, "Enter the robot's world size (Between 1 to 99)");
if (worldSizeString == null)
break;
try{
robotsWorldSize = Integer.parseInt(worldSizeString);
} catch (Exception ex){
continue;
}
validWorldSize = robotsWorldSize > 0 && robotsWorldSize < 100;
}
robotsWorld = new RobotsWorld(robotsWorldSize);
}
}
RobotsWorldPanel
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class RobotsWorldPanel extends JPanel {
private static final int ROBOTS_NUMBER = 5;
private static final int NUMBER_OF_MOVES_TO_MOVE = 30;
private RobotsWorld robotsWorld;
private Random random = new Random();
private static Position[] robotsPositions = new Position[ROBOTS_NUMBER];
private static Map<Integer, Color> robotsColors = new HashMap<>();
public RobotsWorldPanel(RobotsWorld robotsWorld) {
setSize(RobotsWorldSimulator.CELL_WIDTH * RobotsWorldSimulator.robotsWorldSize,
RobotsWorldSimulator.CELL_HEIGHT * RobotsWorldSimulator.robotsWorldSize );
this.robotsWorld = robotsWorld;
initializeRobots();
setLayout(new GridLayout(RobotsWorldSimulator.robotsWorldSize, RobotsWorldSimulator.robotsWorldSize ));
setVisible(true);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
drawGameBoard(g);
drawRobots(g);
moveRandomRobot();
}
private void drawGameBoard(Graphics g) {
for (int i = 0; i <= RobotsWorldSimulator.robotsWorldSize; i++) {
g.drawLine(0, i * RobotsWorldSimulator.CELL_HEIGHT,
RobotsWorldSimulator.CELL_WIDTH * RobotsWorldSimulator.robotsWorldSize,
i * RobotsWorldSimulator.CELL_HEIGHT);
}
for (int i = 0; i <= RobotsWorldSimulator.robotsWorldSize; i++) {
g.drawLine(i * RobotsWorldSimulator.CELL_WIDTH, 0,
i * RobotsWorldSimulator.CELL_WIDTH,
RobotsWorldSimulator.CELL_HEIGHT * RobotsWorldSimulator.robotsWorldSize);
}
}
private void drawRobots(Graphics g) {
for (int robotIndex = 0; robotIndex < ROBOTS_NUMBER; robotIndex++){
Position robotPosition = robotsPositions[robotIndex];
Robot targetRobot = robotsWorld.getRobot(robotPosition);
Color robotColor = robotsColors.get(targetRobot.getRobotId());
drawRobot(g, robotPosition.getX(), robotPosition.getY(), robotColor, targetRobot.getRobotDirection());
}
}
private void drawRobot(Graphics g, int row, int col, Color robotColor, int robotDirection) {
g.setColor(robotColor);
g.fillOval(row * RobotsWorldSimulator.CELL_WIDTH, col * RobotsWorldSimulator.CELL_HEIGHT,
RobotsWorldSimulator.CELL_WIDTH, RobotsWorldSimulator.CELL_HEIGHT);
String robotDirectionSign = "";
if (robotDirection == Robot.DIRECTION_DOWN){
robotDirectionSign = "v";
} else if (robotDirection == Robot.DIRECTION_RIGHT){
robotDirectionSign = ">";
} else if (robotDirection == Robot.DIRECTION_UP){
robotDirectionSign = "^";
} else if (robotDirection == Robot.DIRECTION_LEFT){
robotDirectionSign = "<";
}
g.setColor(Color.WHITE);
g.drawString(robotDirectionSign, (row * RobotsWorldSimulator.CELL_WIDTH) + RobotsWorldSimulator.CELL_WIDTH / 2,
(col * RobotsWorldSimulator.CELL_HEIGHT) + RobotsWorldSimulator.CELL_HEIGHT / 2);
}
// Generating random color for each robot
private void initializeRobots() {
// Inserting new robots to the world
for (int robotIndex = 0; robotIndex < ROBOTS_NUMBER; robotIndex++) {
// Set random position
int x = random.nextInt(RobotsWorldSimulator.robotsWorldSize);
int y = random.nextInt(RobotsWorldSimulator.robotsWorldSize);
Position robotPosition = new Position(x,y);
robotsPositions[robotIndex] = robotPosition;
try {
robotsWorld.addRobot(robotPosition);
} catch (IllegalPositionException ex){
return;
}
Robot addedRobot = robotsWorld.getRobot(robotPosition);
// Adding the robot to the colors map
robotsColors.put(addedRobot.getRobotId(), new Color(random.nextFloat(), random.nextFloat(), random.nextFloat()));
}
}
// Moves a random robot a specified number of moves
private void moveRandomRobot() {
int randomRobot = random.nextInt(ROBOTS_NUMBER);
Position robotPosition = robotsPositions[randomRobot];
int possibleWaysToMove = Robot.NUMBER_OF_DIRECTIONS;
for (int moveNumber = 0; moveNumber < NUMBER_OF_MOVES_TO_MOVE && possibleWaysToMove > 0; moveNumber++){
try{
robotsWorld.moveRobot(robotPosition);
// THE PROBLEM IS HERE - WHY ISN'T paintComponent fired??
repaint();
// 1 second sleep for graphics purposes.
// try {
// Thread.sleep(10000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
possibleWaysToMove = Robot.NUMBER_OF_DIRECTIONS;
} catch (IllegalPositionException ex) {
// Turns the robot right in case of failure.
Robot targetRobot = robotsWorld.getRobot(robotPosition);
targetRobot.turnRight();
possibleWaysToMove--;
}
}
if (possibleWaysToMove == 0)
{
JOptionPane.showMessageDialog( this, "The robot in position" + robotPosition + "has no where left to move!");
return;
}
}
}