简体   繁体   English

重绘未调用

[英]Repaint not being called

I'm making a simple maze solving algorithm (A* but that's not pertinent) and a GUI to display the agent navigating through the maze. 我正在制作一个简单的迷宫求解算法(A *,但不相关)和一个GUI,以显示在迷宫中导航的代理。 I have a MapModel class that deals with the state and a MapView class that draws everything to a JPanel. 我有一个处理状态的MapModel类和一个将所有内容绘制到JPanel的MapView类。 I have the MapModel class call repaint everytime the state changes, but when I need my unit to animate (in the moveAgent() method), repaint isn't getting called. 每当状态改变时,我都有MapModel类调用重绘,但是当我需要我的单元进行动画处理(在moveAgent()方法中)时,不会调用重绘。 I've debugged the program and the repaint method is being reached every "frame" but MapView's paintComponent method isn't being called. 我已经调试了程序,并且每个“帧”都达到了repaint方法,但是没有调用MapView的paintComponent方法。

I'm relatively new to UI and animation, I haven't coded much else other than scripts and C programs, so I might be doing this completely wrong. 我对UI和动画还比较陌生,除了脚本和C程序外,我没有编写其他代码,因此我做错了完全错误的代码。 Let me know if I should redesign any of my classes to fit better with standard java swing practices! 让我知道是否应该重新设计我的任何类以使其更适合标准Java swing练习!

Here's my code. 这是我的代码。 There are other classes, but I'm quite sure they're unrelated to the problem. 还有其他的类,但是我很确定它们与问题无关。 I can post them as well if you'd like. 如果您愿意,我也可以发布它们。

EDIT: I forgot to mention that repaint does work sometimes, just not in moveAgent(). 编辑:我忘了提到重绘有时可以工作,只是在moveAgent()中不起作用。 When I call it from createRandomObstacles(), it paints correctly. 当我从createRandomObstacles()调用它时,它可以正确绘制。

MapModel.java: MapModel.java:

import java.util.ArrayList;
import java.util.PriorityQueue;
import java.awt.Point;
import java.util.HashMap;
public class MapModel {
    int width, height, start_diameter, speed;
    ArrayList<Obstacle> obstacle_list = new ArrayList<Obstacle>();
    Agent agent;
    GridSpaceManager grid_manager;
    String current_algorithm = "NONE";
    ArrayList<Point> subgoal_list;
    MapView map_view;
    boolean animate = false;
    AnimationManager animation_manager = new AnimationManager();

    public MapModel(int size, MapView map_view)
    {
        this.width = size;
        this.height = size;
        this.map_view = map_view;
    }

    public void updateMapModel (){
        map_view.repaint();
    }
    //if obstacles can't fit then method returns
    public void createRandomObstacles(int num_obstacles, int start_diameter)
    {
        this.start_diameter = start_diameter;
        obstacle_list.clear();
        ArrayList<Point> point_list = new ArrayList<Point>();
        for(int i = 0; i < num_obstacles; i++) {
            int rand_x = (int)(Math.random()*(width-start_diameter))+start_diameter;
            int rand_y = (int)(Math.random()*(height-start_diameter))+start_diameter;
            point_list.add(new Point(rand_x, rand_y));

        }


        for(int i = 0; i < num_obstacles; i++) {


            double min_distance = Double.MAX_VALUE;
            Point p1 = point_list.get(i);
            for(int j = 0; j < num_obstacles; j++) {
                Point p2 = point_list.get(j);
                if(j != i && p1.distance(p2) < min_distance)
                    min_distance = p1.distance(p2);
            }
            min_distance = Math.sqrt(min_distance*min_distance/2);
            int min_int = (int)(min_distance/2);
            if(min_int > 1) {
                int width = (int)(Math.random()*(min_int)); 
                width = Math.min(width, Math.max(p1.x, this.width - p1.x));
                int height = (int)(Math.random()*(min_int));
                height = Math.min(height, Math.max(p1.y, this.height - p1.y));
                if(p1.x + width > this.width - start_diameter && p1.y + height > this.height - start_diameter) {
                    width = this.width - start_diameter - p1.x; 
                    height = this.height - start_diameter - p1.y;
                }

                if(!(width < 0 && height < 0))
                    obstacle_list.add(new Obstacle(p1.x, p1.y, width, height));
            }
        }

        updateMapModel();
    }

    public void moveAgent() {
        if(animation_manager.running) {
            animation_manager.act();

            double speed = Math.sqrt(width*height/10);
            Point p = subgoal_list.get(0);
            if(p.x == agent.x && p.y == agent.y) {
                if(subgoal_list.size() == 1) {
                    animate = false;
                    return;
                }
                subgoal_list.remove(0);
                p = subgoal_list.get(0);
            }

            double distance = Point.distance(agent.x, agent.y, p.x, p.y);
            double delta_x = (p.x - agent.x)/distance;
            double delta_y = (p.y - agent.y)/distance;
            double distance2 = Math.sqrt(delta_x*delta_x + delta_y+delta_y);
            if(distance2 > distance) {
                agent.x = p.x;
                agent.y = p.y;
            }
            else {
                agent.x += delta_x;
                agent.y += delta_y;
            }
            long sleep_time = animation_manager.timeTillNextFrame();
            if(sleep_time > 0)
                try {
                    Thread.sleep(sleep_time);
                }
                catch(InterruptedException e) {

                }
            updateMapModel();
            moveAgent();
        }
        else {
            endPathfinding();
        }
    }

    public void startAnimation(int agent_diameter, boolean animate) {
        agent = new Agent(0,0,agent_diameter);
        this.animate = animate;

        animation_manager.start();
        moveAgent();
    }

    public void startPathfinding(String algorithm, int agent_diameter, boolean animate) {

        if(algorithm.equals("A*")) {
            startAStar(agent_diameter);
            this.current_algorithm = "A*";
        }
        if(subgoal_list == null) {
            this.current_algorithm = "NONE";
        }
        startAnimation(agent_diameter, animate);
    }

    public void endPathfinding() {
        agent = null;
        subgoal_list = null;
        animation_manager.end();
        this.current_algorithm = "NONE";
    }

    public void startAStar(int agent_diameter) {
        grid_manager = new GridSpaceManager(obstacle_list, width, height);
        if(agent_diameter > start_diameter) return;
        agent = new Agent(agent_diameter/2, agent_diameter/2, agent_diameter);
        subgoal_list = AStar(grid_manager.getNode(0, 0), grid_manager.getNode(width - 1, height - 1));
    }

    public ArrayList<Point> AStar(SearchSpaceNode start, SearchSpaceNode goal) {
        Point start_point = start.point_list[0];
        Point goal_point = goal.point_list[0];
        PriorityQueue<SearchSpaceNode> open_set = new PriorityQueue<SearchSpaceNode>();
        ArrayList<SearchSpaceNode> closed_set = new ArrayList<SearchSpaceNode>();

        HashMap<SearchSpaceNode, SearchSpaceNode> came_from = new HashMap<SearchSpaceNode, SearchSpaceNode>();
        HashMap<SearchSpaceNode, Integer> g_score = new HashMap<SearchSpaceNode, Integer>();
        HashMap<SearchSpaceNode, Integer> f_score = new HashMap<SearchSpaceNode, Integer>();

        int start_f_value = (int)manhattan_distance(start,goal);

        g_score.put(start, 0);
        f_score.put(start, start_f_value);

        start.f_value = start_f_value;
        open_set.add(start);

        while(open_set.size() > 0) {
            SearchSpaceNode current = open_set.poll();


            if(current == goal) {
                ArrayList<Point> subgoal_list = reconstructPath(came_from, current);
                subgoal_list.add(goal_point);
                return subgoal_list;
            }

            closed_set.add(current);
            ArrayList<SearchSpaceNode> neighbors = current.getNeighbors();
            for(int i = 0; i < neighbors.size(); i++) {
                SearchSpaceNode neighbor = neighbors.get(i);
                if(closed_set.contains(neighbor))
                    continue;

                int tentative_g_score = g_score.get(current) + 1;

                if(!open_set.contains(neighbor) || !g_score.containsKey(neighbor) 
                        || tentative_g_score < g_score.get(neighbor)) {
                    int tentative_f_score = tentative_g_score + (int)manhattan_distance(neighbor, goal);

                    came_from.put(neighbor, current);
                    g_score.put(neighbor, tentative_g_score);
                    f_score.put(neighbor, tentative_f_score);
                    neighbor.f_value = tentative_f_score;
                    if(!open_set.contains(neighbor))
                        open_set.add(neighbor);
                }

            }
        }



        return null;
    }

    public ArrayList<Point> reconstructPath(
            HashMap<SearchSpaceNode,SearchSpaceNode> came_from,SearchSpaceNode current_node) {
        ArrayList<Point> subgoal_list = new ArrayList<Point>();


        while(came_from.containsKey(current_node)) {
            SearchSpaceNode temp = came_from.get(current_node); 
            subgoal_list.add(0, temp.point_list[0]);
            came_from.remove(current_node);
            current_node = temp;
        }
        return subgoal_list;
    }

    public double manhattan_distance(SearchSpaceNode start, SearchSpaceNode goal) {
        Point start_point = start.point_list[0];
        Point goal_point = goal.point_list[0];
        return Math.sqrt(Math.pow(goal_point.x - start_point.x,2) + Math.pow(goal_point.x - start_point.x,2));
        //return Math.abs(goal_point.x - start_point.x) + Math.abs(goal_point.y - start_point.y);
    }

    public String algorithmRunning(){return current_algorithm;}
}

class AnimationManager {
    boolean running = false;
    int frame_number = -1;
    int milliseconds_per_frame = 500;
    long start_time = -1;


    public void start() {
        running  = true;
        start_time = System.currentTimeMillis();
        frame_number = 0;
    }

    public void end() {
        running = false;
        start_time = frame_number = -1;
    }

    public void act() {
        frame_number++;
    }
    public long timeTillNextFrame() {
        return  (frame_number + 1)*milliseconds_per_frame - (System.currentTimeMillis() - start_time);
    }
}

MapView.java: MapView.java:

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;

public class MapView extends JPanel{

    private int size, actual_map_size;
    MapModel map_model;
    Point current_subgoal = null;

    int frame_number = 0;
    long start_time;
    public MapView(int size)
    {
        this.setBounds(0,200,600,600);

        this.size = size;
    }
    boolean starting_print = true;
    public void paintComponent(Graphics g) {

        int x_offset = 10, y_offset = 10;
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        g.fillRect((600-size)/2 + x_offset - 2, y_offset - 2,size + 5, size + 5);
        g.setColor(Color.WHITE);
        g.fillRect((600-size)/2 + x_offset - 1, y_offset - 1,size+3,size+3);

        g.setColor(Color.GREEN);

        if(this.map_model != null) {
            ArrayList<Obstacle> obstacle_list = map_model.obstacle_list;
            for(int i = 0; i < obstacle_list.size(); i++) {
                Obstacle o = obstacle_list.get(i);
                g.fillRect(scaleX(o.x) + x_offset,scale(o.y) + y_offset,
                        scale(o.width),scale(o.height));
            }

            g.setColor(Color.RED);
            if(map_model.current_algorithm.equals("A*")) {
                GridSpaceManager grid = map_model.grid_manager;

                for(int i = 0; i < map_model.width; i++) {
                    for(int j = 0; j< map_model.height; j++) {
                        SearchSpaceNode node = grid.getNode(i, j);
                        if(node != null) {
                            Point p = node.point_list[0];
                            g.drawRect(scaleX(p.x) + x_offset, scale(p.y) + y_offset, scale(1), scale(1));
                        }
                    }
                }
            }

            g.setColor(Color.BLUE);
            Agent agent = map_model.agent;


            if(agent != null) {
                g.fillOval(scaleX(agent.x) + x_offset, scale(agent.y) + y_offset,
                        Math.max(2,scale(agent.diameter)), Math.max(2,scale(agent.diameter)));
            }

        }

    }

    private int scaleX(int x) {
        double scale = ((double)size) / ((double)actual_map_size);
        return (int)(((double)x)*scale)+(600-size)/2;
    }
    private int scale(int val) {
        double scale = ((double)size) / ((double)actual_map_size);
        return (int)(((double)val)*scale);
    }

    public void setMapModel(MapModel map) {
        this.map_model = map;
    }

    public void setMapScale(int actual_map_size) {
        this.actual_map_size = actual_map_size;
    }
}

I redesigned my code to use the Timer class at the suggestion of MadProgrammer. 在MadProgrammer的建议下,我重新设计了代码以使用Timer类。 It was a much neater way to get my animations working! 这是使我的动画工作更加整洁的方法! Here's the new code below. 这是下面的新代码。 The MapView class remains unchanged. MapView类保持不变。

MapModel.java MapModel.java

import java.util.ArrayList;
import javax.swing.*;
import java.awt.event.*;

import java.util.PriorityQueue;
import java.awt.Point;
import java.util.HashMap;
public class MapModel implements ActionListener{
    boolean running = false;
    int milliseconds_per_frame = 500;
    Timer timer = new Timer(milliseconds_per_frame, this);

    int width, height, start_diameter, speed;
    ArrayList<Obstacle> obstacle_list = new ArrayList<Obstacle>();
    Agent agent;
    GridSpaceManager grid_manager;
    String current_algorithm = "NONE";
    ArrayList<Point> subgoal_list;
    MapView map_view;
    boolean animate = false;

    public MapModel(int size, MapView map_view)
    {
        this.width = size;
        this.height = size;
        this.map_view = map_view;
    }

    public void updateMapModel (){
        map_view.repaint();
    }
    //if obstacles can't fit then method returns
    public void createRandomObstacles(int num_obstacles, int start_diameter)
    {
        this.start_diameter = start_diameter;
        obstacle_list.clear();
        ArrayList<Point> point_list = new ArrayList<Point>();
        for(int i = 0; i < num_obstacles; i++) {
            int rand_x = (int)(Math.random()*(width-start_diameter))+start_diameter;
            int rand_y = (int)(Math.random()*(height-start_diameter))+start_diameter;
            point_list.add(new Point(rand_x, rand_y));
            /*
            double min_distance = Double.MAX_VALUE;
            Point p1 = point_list.get(i);
            for(int j = 0; j < point_list.size(); j++) {
                Point p2 = point_list.get(j);
                if(j != i && p1.distance(p2) < min_distance)
                    min_distance = p1.distance(p2);
            }
            min_distance = Math.sqrt(min_distance*min_distance/2);
            int min_int = (int)(min_distance/2);
            if(min_int > 1) {
                int width = (int)(Math.random()*(min_int)); 
                width = Math.min(width, Math.max(p1.x, this.width - p1.x));
                int height = (int)(Math.random()*(min_int));
                height = Math.min(height, Math.max(p1.y, this.height - p1.y));
                if(p1.x + width > this.width - start_diameter && p1.y + height > this.height - start_diameter) {
                    width = this.width - start_diameter - p1.x; 
                    height = this.height - start_diameter - p1.y;
                }

                if(!(width < 0 && height < 0))
                    obstacle_list.add(new Obstacle(p1.x, p1.y, width, height));
            }
            */
        }


        for(int i = 0; i < num_obstacles; i++) {


            double min_distance = Double.MAX_VALUE;
            Point p1 = point_list.get(i);
            for(int j = 0; j < num_obstacles; j++) {
                Point p2 = point_list.get(j);
                if(j != i && p1.distance(p2) < min_distance)
                    min_distance = p1.distance(p2);
            }
            min_distance = Math.sqrt(min_distance*min_distance/2);
            int min_int = (int)(min_distance/2);
            if(min_int > 1) {
                int width = (int)(Math.random()*(min_int)); 
                width = Math.min(width, Math.max(p1.x, this.width - p1.x));
                int height = (int)(Math.random()*(min_int));
                height = Math.min(height, Math.max(p1.y, this.height - p1.y));
                if(p1.x + width > this.width - start_diameter && p1.y + height > this.height - start_diameter) {
                    width = this.width - start_diameter - p1.x; 
                    height = this.height - start_diameter - p1.y;
                }

                if(!(width < 0 && height < 0))
                    obstacle_list.add(new Obstacle(p1.x, p1.y, width, height));
            }
        }

        updateMapModel();
    }

    public void moveAgent() {
        if(animate) {


            double speed = Math.sqrt(width*height/10);
            Point p = subgoal_list.get(0);
            if(p.x == agent.x && p.y == agent.y) {
                if(subgoal_list.size() == 1) {
                    animate = false;
                    return;
                }
                subgoal_list.remove(0);
                p = subgoal_list.get(0);
            }

            double distance = Point.distance(agent.x, agent.y, p.x, p.y);
            double delta_x = (p.x - agent.x)/distance;
            double delta_y = (p.y - agent.y)/distance;
            double distance2 = Math.sqrt(delta_x*delta_x + delta_y+delta_y);
            if(distance2 > distance) {
                agent.x = p.x;
                agent.y = p.y;
            }
            else {
                agent.x += delta_x;
                agent.y += delta_y;
            }
            updateMapModel();
        }
        else {
            endPathfinding();
        }
    }

    public void startAnimation(int agent_diameter, boolean animate) {
        agent = new Agent(0,0,agent_diameter);
        this.animate = animate;
        timer.start();
        moveAgent();
    }

    public void startPathfinding(String algorithm, int agent_diameter, boolean animate) {

        if(algorithm.equals("A*")) {
            startAStar(agent_diameter);
            this.current_algorithm = "A*";
        }
        if(subgoal_list == null) {
            this.current_algorithm = "NONE";
        }
        startAnimation(agent_diameter, animate);
    }

    public void endPathfinding() {
        agent = null;
        subgoal_list = null;
        timer.stop();
        this.current_algorithm = "NONE";
    }

    public void startAStar(int agent_diameter) {
        grid_manager = new GridSpaceManager(obstacle_list, width, height);
        if(agent_diameter > start_diameter) return;
        agent = new Agent(agent_diameter/2, agent_diameter/2, agent_diameter);
        subgoal_list = AStar(grid_manager.getNode(0, 0), grid_manager.getNode(width - 1, height - 1));
    }

    public ArrayList<Point> AStar(SearchSpaceNode start, SearchSpaceNode goal) {
        Point start_point = start.point_list[0];
        Point goal_point = goal.point_list[0];
        PriorityQueue<SearchSpaceNode> open_set = new PriorityQueue<SearchSpaceNode>();
        ArrayList<SearchSpaceNode> closed_set = new ArrayList<SearchSpaceNode>();

        HashMap<SearchSpaceNode, SearchSpaceNode> came_from = new HashMap<SearchSpaceNode, SearchSpaceNode>();
        HashMap<SearchSpaceNode, Integer> g_score = new HashMap<SearchSpaceNode, Integer>();
        HashMap<SearchSpaceNode, Integer> f_score = new HashMap<SearchSpaceNode, Integer>();

        int start_f_value = (int)manhattan_distance(start,goal);

        g_score.put(start, 0);
        f_score.put(start, start_f_value);

        start.f_value = start_f_value;
        open_set.add(start);

        while(open_set.size() > 0) {
            SearchSpaceNode current = open_set.poll();


            if(current == goal) {
                ArrayList<Point> subgoal_list = reconstructPath(came_from, current);
                subgoal_list.add(goal_point);
                return subgoal_list;
            }

            closed_set.add(current);
            ArrayList<SearchSpaceNode> neighbors = current.getNeighbors();
            for(int i = 0; i < neighbors.size(); i++) {
                SearchSpaceNode neighbor = neighbors.get(i);
                if(closed_set.contains(neighbor))
                    continue;

                int tentative_g_score = g_score.get(current) + 1;

                if(!open_set.contains(neighbor) || !g_score.containsKey(neighbor) 
                        || tentative_g_score < g_score.get(neighbor)) {
                    int tentative_f_score = tentative_g_score + (int)manhattan_distance(neighbor, goal);

                    came_from.put(neighbor, current);
                    g_score.put(neighbor, tentative_g_score);
                    f_score.put(neighbor, tentative_f_score);
                    neighbor.f_value = tentative_f_score;
                    if(!open_set.contains(neighbor))
                        open_set.add(neighbor);
                }

            }
        }



        return null;
    }

    public ArrayList<Point> reconstructPath(
            HashMap<SearchSpaceNode,SearchSpaceNode> came_from,SearchSpaceNode current_node) {
        ArrayList<Point> subgoal_list = new ArrayList<Point>();


        while(came_from.containsKey(current_node)) {
            SearchSpaceNode temp = came_from.get(current_node); 
            subgoal_list.add(0, temp.point_list[0]);
            came_from.remove(current_node);
            current_node = temp;
        }
        return subgoal_list;
    }

    public double manhattan_distance(SearchSpaceNode start, SearchSpaceNode goal) {
        Point start_point = start.point_list[0];
        Point goal_point = goal.point_list[0];
        return Math.sqrt(Math.pow(goal_point.x - start_point.x,2) + Math.pow(goal_point.x - start_point.x,2));
        //return Math.abs(goal_point.x - start_point.x) + Math.abs(goal_point.y - start_point.y);
    }

    public String algorithmRunning(){return current_algorithm;}

    public void actionPerformed(ActionEvent e) {
        if(animate) {
            moveAgent();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM