Java 在所有代码运行之前,JFrame不会更新其绘制
所以我有一个非常奇怪的问题,我只是在学习JFrames/Panels,根据我的理解,如果我在框架中添加一个新组件,我必须调用revalidate()以使框架使用该组件 在下面所示的A*的实现中,算法的进度在整个while()循环中使用repaint()显示 这将显示算法运行时的进度,并且在我决定尝试向gui添加菜单之前工作良好 因此,现在我需要能够将Display()组件(它是一个JPanel)添加到帧中,并使其像以前一样运行,在运行时显示算法。但是目前有大约一秒钟的暂停,并且只绘制算法的最终状态,即好像它立即只绘制while()循环中的最后一个repaint()调用 这里的任何帮助都是感激的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)添加到帧中,并使其像以前一样运行,在运行时显示算法。但是目前有大约一秒钟的暂停,并且只绘制算法的最终状
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);
}
}