好的,我按你的意愿写了MCVE。关键是我正在从另一个线程(RecursiveThread)重新绘制MazePanel,但它不起作用。仅当RecursiveThread结束工作时才重新绘制JPanel ...
MCVE:
package main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import com.sun.prism.Graphics;
public class Main {
public static Gui gui;
public static int[] directionArray = {0, 1, 2, 3};
public static int[][] maze = {
{2, 2, 2, 0, 2, 2, 2},
{2, 1, 1, 1, 2, 1, 2},
{2, 1, 2, 2, 2, 1, 2},
{2, 1, 1, 1, 1, 1, 2},
{2, 2, 2, 3, 2, 2, 2}
};
public static RecursiveAlgorithm recursiveAlgorithm;
public static Thread alghoritmThread;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
gui = new Gui();
}
});
}
}
class MazePanel extends JPanel {
private int rows;
private int columns;
@Override
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
rows = Main.maze.length;
columns = Main.maze[0].length;
Graphics2D g2 = (Graphics2D) g;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
switch (Main.maze[r][c]) {
case 0:
g2.setColor(Color.BLUE);
break;
case 1:
g2.setColor(Color.GRAY);
break;
case 2:
g2.setColor(Color.GREEN);
break;
case 3:
g2.setColor(Color.RED);
break;
case 4:
g2.setColor(Color.YELLOW);
break;
case 5:
g2.setColor(Color.BLACK);
break;
default:
break;
}
g.fillRect(c * 64, r * 64, 64, 64);
}
}
}
public void paint(Graphics g) {
}
}
class GuiActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
if (event.getSource() == Gui.startButton) {
Main.recursiveAlgorithm = new RecursiveAlgorithm();
Main.alghoritmThread = new Thread(Main.recursiveAlgorithm);
Main.alghoritmThread.run();
}
}
}
class Gui extends JFrame {
public static JScrollPane scrollPane;
public static MazePanel mazePanel;
private JMenuBar menuBar;
public static JButton startButton;
public Gui() {
setPreferredSize(new Dimension(800, 600));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
startButton = new JButton("START");
startButton.addActionListener(new GuiActionListener());
menuBar = new JMenuBar();
menuBar.add(startButton);
mazePanel = new MazePanel();
scrollPane = new JScrollPane(mazePanel);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setBackground(Color.LIGHT_GRAY);
setJMenuBar(menuBar);
add(scrollPane);
pack();
setVisible(true);
}
}
class RecursiveAlgorithm implements Runnable{
private int columns;
private int rows;
private int startX;
private int startY;
public RecursiveAlgorithm() {
rows = Main.maze.length;
columns = Main.maze[0].length;
}
private boolean findPath(int x, int y) {
System.out.println("findPath("+ x + "," + y +")");
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
System.out.print(Main.maze[r][c]);
}
System.out.println();
}
if (y < 0 || y >= rows) return false;
if (x < 0 || x >= columns) return false;
if (Main.maze[x][y] == 3) {
Main.maze[x][y] = 5;
Main.gui.mazePanel.repaint();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
if (Main.maze[x][y] != 0)
if (Main.maze[x][y] != 1) return false;
Main.maze[x][y] = 5;
Main.gui.mazePanel.repaint();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (goInDirectory(0, x, y)) return true;
if (goInDirectory(1, x, y)) return true;
if (goInDirectory(2, x, y)) return true;
if (goInDirectory(3, x, y)) return true;
Main.maze[x][y] = 4;
Main.gui.mazePanel.repaint();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
private boolean goInDirectory(int index, int x, int y) {
switch (Main.directionArray[index]) {
case 0:
if (findPath(x,y-1)) return true;
break;
case 1:
if (findPath(x+1,y)) return true;
break;
case 2:
if (findPath(x-1,y)) return true;
break;
case 3:
if (findPath(x,y+1)) return true;
break;
}
return false;
}
private void findStart() {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
if (Main.maze[r][c] == 0) {
startX = r;
startY = c;
}
}
}
}
@Override
public void run() {
System.out.println("Thread started");
findStart();
boolean pathFound = findPath(startX, startY);
if (pathFound) {
System.out.println("Path found");
} else {
System.out.println("Path NOT found!");
}
}
}
问题2(offtopic):在我的真实代码中,我在JPanel上绘制图像并覆盖MazePanel中的paint()而不是paintComponent()。它对我来说很好。但是当我尝试将代码从paint()移动到paintComponent()时,它停止工作(然后我的MazePanel上没有任何东西)。这是代码(工作正常):
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
public void paint(Graphics g) {
if(Main.mazeReady) {
rows = Main.maze.length;
columns = Main.maze[0].length;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
g.drawImage(Main.maze[r][c].getGraphic(),
c * TileGraphicsHandler.TILE_HEIGHT,
r * TileGraphicsHandler.TILE_WIDTH,
null);
}
}
}
}
这样就不起作用了:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(Main.mazeReady) {
rows = Main.maze.length;
columns = Main.maze[0].length;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
g.drawImage(Main.maze[r][c].getGraphic(),
c * TileGraphicsHandler.TILE_HEIGHT,
r * TileGraphicsHandler.TILE_WIDTH,
null);
}
}
}
}
public void paint(Graphics g) {
}
问题3(offtopic):如何划分我的RecursiveAlgorithm,所以我可以添加gui按钮“STEP FORWARD”并以这种方式控制我的算法(通过在我的RecursiveAlgorithm中移动alghoritm并只移动一行/几行) ?
答案 0 :(得分:3)
让我看看能否为您提供一些基本建议。您附加的代码库相当大,坦率地说,有点混乱。
paint()
方法。您已正确覆盖paintComponent(...)
,但覆盖paint()
方法不正确,可能会导致问题。MazePanel
类,其中包含Tile[][]
给定Maze
的句柄。请考虑创建一个Maze
类,其中包含Tile[][]
,以及与Maze
相关联的所有关联状态,然后您可以从{Maze
引用MazePanel
{1}}。Maze
课程添加一个方法,该方法可以向迷宫的解决方案迈出一步(例如stepTowardsSolution()
)。它可以返回一个枚举或布尔值,表示它是否已完成。在MazePanel
中,有一个名为solve()
的方法:
while(maze.stepTowardsSolution() != done) {
repaint();
sleepABit();
}