首页 > 解决方案 > 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;
        }
    }
}

标签: javaswingjpanel

解决方案


推荐阅读