好的,我根据需要编写了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(题外话):在我的真实代码中,im在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(题外话):如何划分RecursiveAlgorithm,以便我可以向gui按钮“ STEP FORWARD”添加并以这种方式控制算法(通过注入算法并在RecursiveAlgorithm中仅移动一条/几行)?

最佳答案

让我看看是否可以为您提供一些基本建议。您附加的代码库很大,坦率地说,有点混乱。


不要覆盖paint()方法。您已经正确覆盖了paintComponent(...),但是覆盖paint()方法是不正确的,并且可能会导致问题。
您有一个MazePanel类,该类具有给定Tile[][]Maze句柄。考虑改为创建一个具有Maze且与Tile[][]关联的所有关联状态的Maze类,然后可以从Maze引用该MazePanel
将方法添加到您的Maze类中,该方法可以一步一步解决迷宫问题(例如stepTowardsSolution())。它可以返回一个指示是否完成的枚举或布尔值。
MazePanel中,有一个称为solve()的方法可以执行以下操作:

while(maze.stepTowardsSolution() != done) {
    repaint();
    sleepABit();
}

09-16 03:11