Java 在所有代码运行之前,JFrame不会更新其绘制

Java 在所有代码运行之前,JFrame不会更新其绘制,java,swing,jframe,jpanel,event-dispatch-thread,Java,Swing,Jframe,Jpanel,Event Dispatch Thread,所以我有一个非常奇怪的问题,我只是在学习JFrames/Panels,根据我的理解,如果我在框架中添加一个新组件,我必须调用revalidate()以使框架使用该组件 在下面所示的A*的实现中,算法的进度在整个while()循环中使用repaint()显示 这将显示算法运行时的进度,并且在我决定尝试向gui添加菜单之前工作良好 因此,现在我需要能够将Display()组件(它是一个JPanel)添加到帧中,并使其像以前一样运行,在运行时显示算法。但是目前有大约一秒钟的暂停,并且只绘制算法的最终状

所以我有一个非常奇怪的问题,我只是在学习JFrames/Panels,根据我的理解,如果我在框架中添加一个新组件,我必须调用revalidate()以使框架使用该组件

在下面所示的A*的实现中,算法的进度在整个while()循环中使用repaint()显示

这将显示算法运行时的进度,并且在我决定尝试向gui添加菜单之前工作良好

因此,现在我需要能够将Display()组件(它是一个JPanel)添加到帧中,并使其像以前一样运行,在运行时显示算法。但是目前有大约一秒钟的暂停,并且只绘制算法的最终状态,即好像它立即只绘制while()循环中的最后一个repaint()调用

这里的任何帮助都是感激的

import java.awt.event.*;
import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import javax.swing.*;

public class aStar {
    /** Width of the GUI */
    private static final int WIDTH = 1280;
    /** Height of the GUI */
    private static final int HEIGHT = 720;

    public static JFrame frame = new JFrame("A* Search Algorithm");

    public static Set<Node> closedSet;
    public static Queue<Node> openSet;

    public static String fileName;

    public static void findPath() {
        try {
            // Initialise the open and closed sets
            closedSet = new HashSet<>();
            openSet = new PriorityQueue<>((a, b) -> Double.compare(a.f, b.f));

            // Process the map
            Map map = new Map(fileName);
            openSet.add(map.start);
            frame.add(new Display(map));
            frame.revalidate();

            /**
             * The A* Algorithm
             */
            while (true) {
                Node current = openSet.poll();

                if (current == map.end) {
                    // We have reached the goal -- render the path and exit
                    renderPath(current, frame);
                    System.out.println("Done!");
                    return;
                }

                // Check through every neighbor of the current node
                for (Node n : map.neighborsOf(current)) {
                    // if its closed or a wall, ignore it
                    if (closedSet.contains(n)) {
                        continue;
                    }

                    // Set the node's h value
                    n.h = heuristic(n, map.end);

                    // Calculate the possible total cost of moving to this node from start
                    double tentativeG = calculateCost(current, n);

                    // Check whether the cost we've calculated is better than the node's current
                    // cost. If so, the path we're currently on is better so we update its g
                    // and add it to openSet
                    if (tentativeG < n.g) {
                        n.setG(tentativeG);
                        n.previous = current;

                        // We need to remove and add the node here in case it already exists
                        // within the PriorityQueue, so that we can force a re-sort.
                        openSet.remove(n);
                        openSet.add(n);
                    }
                }

                // Move current to closedSet
                openSet.remove(current);
                closedSet.add(current);

                // Color the open and closed sets accordingly
                for (Node n : openSet) {
                    n.color = Color.GREEN;
                }
                for (Node n : closedSet) {
                    n.color = Color.RED;
                }

                if (openSet.isEmpty()) {
                    // If openSet is empty, then we failed to find a path to the end
                    // In this case, we render the path to the node with the lowest `h`
                    // value, which is the node closest to the target.

                    Node minHNode = null;
                    for (int x = 0; x < map.width; x++) {
                        for (int y = 0; y < map.height; y++) {
                            Node candidate = map.get(x, y);
                            if (candidate.previous == null)
                                continue;

                            if (minHNode == null) {
                                minHNode = candidate;
                            } else if (candidate.h < minHNode.h) {
                                minHNode = candidate;
                            }
                        }
                    }

                    // Walk through the path we decided on and render it to the user
                    renderPath(minHNode, frame);
                    System.out.println("Failed to reach target. Rendered closest path instead.");
                    return;
                } else {
                    Thread.sleep(10);
                    frame.repaint();
                }
            }
        } catch (FileNotFoundException e) {
            System.err.println("error: Could not find the file \"" + fileName + "\"");
        } catch (InterruptedException e) {
            System.err.println("Error occurred while calling Thread.sleep()");
        } catch (MapException e) {
            System.out.println("error: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        // Build our GUI
        frame.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        frame.setMinimumSize(new Dimension(WIDTH, HEIGHT));
        frame.setMaximumSize(new Dimension(WIDTH, HEIGHT));
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        // Add the menubar and items
        JMenuBar menubar = new JMenuBar();
        frame.setJMenuBar(menubar);
        JMenu file = new JMenu("File");
        menubar.add(file);
        JMenuItem selectMap1 = new JMenuItem("Map 1");
        file.add(selectMap1);

        class selectMapName implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                JMenuItem menuItem = (JMenuItem) e.getSource();
                JPopupMenu menu = (JPopupMenu) menuItem.getParent();
                int index = menu.getComponentZOrder(menuItem);
                onClick(index);
            }

            public void onClick(int index) {
                switch (index) {
                    case 0:
                        fileName = "map1.txt";
                        break;
                    case 1:
                        fileName = "map2.txt";
                        break;
                    case 2:
                        fileName = "map3.txt";
                        break;
                    case 3:
                        fileName = "map4.txt";
                        break;
                    case 4:
                        fileName = "map5.txt";
                        break;
                }
                findPath();
            }
        }
        // Add all the action listeners to the menu items
        selectMap1.addActionListener(new selectMapName());

        // Show the frame
        frame.setVisible(true);
    }

    private static void renderPath(Node startFrom, JFrame frame) {
        // Walk through the path we decided on and render it to the user
        Node temp = startFrom;
        while (temp.previous != null) {
            temp.color = Color.BLUE;
            temp = temp.previous;
        }

        // Repaint with the newly marked path
        frame.repaint();
    }

    /**
     * The heuristic used to determine the validity of a potential path. Currently
     * just returns the euclidian distance. May be better to use taxicab distance if
     * we are not moving diagonals
     * 
     * @param current The current Node
     * @param end     The end Node
     * @return {@code double} The h value for the current Node
     */
    private static double heuristic(Node current, Node end) {
        return Math.hypot(end.x - current.x, end.y - current.y);
    }

    private static double calculateCost(Node current, Node next) {
        double currentG = current.g == Double.MAX_VALUE ? 0 : current.g;
        return currentG + heuristic(current, next);
    }
}```
导入java.awt.event.*;
导入java.io.FileNotFoundException;
导入java.util.HashSet;
导入java.util.PriorityQueue;
导入java.util.Queue;
导入java.util.Set;
导入javax.swing.*;
公共级aStar{
/**GUI的宽度*/
专用静态最终整数宽度=1280;
/**GUI的高度*/
专用静态最终整数高度=720;
公共静态JFrame=新JFrame(“A*搜索算法”);
公共静态设置关闭集;
公共静态队列开放集;
公共静态字符串文件名;
公共静态void findPath(){
试一试{
//初始化打开和关闭的集合
closedSet=newhashset();
openSet=newpriorityqueue((a,b)->Double.compare(a.f,b.f));
//处理地图
映射映射=新映射(文件名);
openSet.add(map.start);
添加(新显示(地图));
frame.revalidate();
/**
*A*算法
*/
while(true){
当前节点=openSet.poll();
如果(当前==map.end){
//我们已经达到了目标--渲染路径并退出
渲染路径(当前,帧);
System.out.println(“完成!”);
返回;
}
//检查当前节点的每个邻居
for(节点n:map.neighborsOf(当前)){
//如果它是封闭的或墙,请忽略它
if(闭合集包含(n)){
继续;
}
//设置节点的h值
n、 h=启发式(n,map.end);
//计算从开始移动到此节点的可能总成本
双电位EG=计算成本(电流,n);
//检查我们计算的成本是否优于节点的当前成本
//如果是这样的话,我们当前的路径会更好,所以我们会更新它的g
//并将其添加到openSet
if(tenativegpublic void onClick(int index) {
    switch (index) {
        // ...
    }
    new Thread(() -> findPath()).start();
}
Thread.sleep(10);
EventQueue.invokeLater(() -> {
    display.addLine(new Line2D(start.x, start.y, end.x, end.y));
    display.repaint();
});
private final Collection<Line2D> lines = new ArrayList<>();

public void addLine(Line2D line) {
    lines.add(line);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g;
    for (Line2D line : lines) {
        g.draw(line);
    }
}