java - JPanel 实现重绘不触发 PaintComponent
问题描述
我有一个 java swing 应用程序,它使用我自己实现的 JPanel 创建一个 JFrame。这个 JPanel 应该包含一个矩阵,应该在每次更改后重新绘制。该矩阵包含元素(在我的应用程序中,这些是“机器人”),在其拟合矩阵单元格中用圆圈表示。
在我的面板中,我试图移动其中一个机器人(意思是 - 将圆圈移动到矩阵中的相邻单元格)30 次,并在每次移动后重新绘制该矩阵。但是,当我在移动机器人后调用 repaint 时,paintComponent()
不会触发。我不知道应该改变什么才能使其按预期工作。
这是我的代码中与问题相关的部分:
机器人世界模拟器
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);
}
}
机器人世界面板
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;
}
}
}
解决方案
推荐阅读
- python - TooManyRequestsException:超出速率。在调用 codnito-idp admin_get_user 函数时
- c++ - c++ sizeof - 需要帮助理解
- node.js - 从 NodeJS 向 REST API 发出请求
- r - 在循环R中标记箱线图的异常值
- istio - 我对 istio 速率限制和命名空间有疑问
- python - 如何使用“get_detail_data”的输出来运行批处理文件
- python - Kivy 从屏幕管理器访问类属性
- php - NGINX 使用 Slim API 框架从子目录重定向到根目录
- spring-boot - nginx google oauth2 的 Spring 安全性在 Nginx 上不起作用
- reactjs - 材料表查找。如何获得选定的值?