Java Swing类中从main调用方法时的睡眠或等待时间

Java Swing类中从main调用方法时的睡眠或等待时间,java,swing,timer,Java,Swing,Timer,我编写了一个Swing类,其中主要只有一个方法调用solve()。此方法实现while循环,并在几乎每一轮中使用另一个方法,此方法称为paint(),只更改9x9 GridLayout中一个JPanel的值,其引用存储在2D数组中 我需要一个计时器在绘图()中,所以在修改面板之前,需要2秒钟。它在第一次调用时执行此操作,但在2秒钟后,它不等待地执行循环的每一轮。目标是在修改任何面板之前,观察2秒钟的时间。我试着使用javax定时器。显然,Thread.sleep()在Swing类中不起作用 im

我编写了一个Swing类,其中主要只有一个方法调用
solve()
。此方法实现while循环,并在几乎每一轮中使用另一个方法,此方法称为paint(),只更改9x9 GridLayout中一个JPanel的值,其引用存储在2D数组中

我需要一个计时器在绘图()中,所以在修改面板之前,需要2秒钟。它在第一次调用时执行此操作,但在2秒钟后,它不等待地执行循环的每一轮。目标是在修改任何面板之前,观察2秒钟的时间。我试着使用javax定时器。显然,Thread.sleep()在Swing类中不起作用

import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.Stack;

public class SudokuApp {

    private JFrame frame;
    int i = 9;
    int j = 9;
    JPanel[][] board = new JPanel[i][j];
    JButton nextButton = new JButton("Resolver");
    Box[][] sudoku = new Box[9][9];
    Box newCurrent = new Box();

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    SudokuApp window = new SudokuApp();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public SudokuApp() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setTitle("Sudoku Solver");
        frame.setBounds(100, 100, 510, 555);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        frame.getContentPane().add(panel, BorderLayout.CENTER);
        panel.setLayout(new GridLayout(i, j));

        //Initiate board

        for (int m = 0; m < i; m++) {
            for (int n = 0; n < j; n++) {
                board[m][n] = new JPanel();
                JTextField textField = new JTextField(1);
                textField.setFont(new Font("Lucida Grande", Font.BOLD, 25));
                board[m][n].add(textField);
                panel.add(board[m][n]);
            }
        }

        Box last = new Box();
        for (int m = 0; m < this.i; m++) {
            for (int n = 0; n < this.j; n++) {
                sudoku[m][n] = new Box(m, n);
                if (m != 0 || n != 0) sudoku[m][n].back = last;
                last = sudoku[m][n];
            }
        }

        //Solve button action listener

        nextButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {
            if (validBoard()) {
                nextButton.setEnabled(false);
                solve();
            }
            else JOptionPane.showMessageDialog(null, "Condiciones iniciales inválidas.");
        } });
        frame.getContentPane().add(nextButton, BorderLayout.SOUTH);
    }

    private boolean validBoard() {
        for (int m = 0; m < i; m++) {
            for (int n = 0; n < j; n++) {
                JTextField current = (JTextField) board[m][n].getComponent(0);
                String text = current.getText();
                if (text.length() == 1 && !text.contains("0")) {
                    try {
                        int number = Integer.parseInt(text);
                        if (!add(number, m, n)) return false;
                        current.setEditable(false);
                    } catch (NumberFormatException e) {
                        return false;
                    }
                } else {
                    current.setText("");
                    current.setEditable(false);
                }
            }
        }
        return true;
    }

    private void solve() {
        int i = 0;
        int j = 0;
        int newI = i + 1;

        while (i < 9) {
            while (j < 9) {
                Box current = sudoku[i][j];

                if (current.number == 0) {
                    HashSet<Integer> possibles = new HashSet<>();
                    HashSet<Integer> takenNumbers = getTakenNumbers(i, j);
                    for (int k = 1; k <= 9; k++) if (!takenNumbers.contains(k)) possibles.add(k);

                    if (possibles.isEmpty()) {
                        current.number = 0;
                        erase(i, j);
                        tryOther(current.back);

                        i = newCurrent.i;
                        newI = i + 1;
                        j = newCurrent.j + 1;
                    } else {
                        for (Integer p : possibles) current.possibles.push(p);
                        current.number = (int) current.possibles.pop();

                        paint(current.number, i, j);

                        j++;
                        newI = i + 1;
                    }
                } else {
                    j++;
                    newI = i + 1;
                }
            }
            i = newI;
            j = 0;
        }
    }

    private void tryOther(Box box) {
        if (box.possibles.empty()) {
            if (box.back != null) {
                if (!box.initial) {
                    box.number = 0;
                    erase(box.i, box.j);
                }
                tryOther(box.back);
            }
            else newCurrent = null;
        } else {
            if (getTakenNumbers(box.i, box.j).contains(box.possibles.peek())) {
                box.possibles.pop();
                tryOther(box);
            }
            newCurrent = box;
            box.number = (int) box.possibles.pop();
            paint(box.number, box.i, box.j);
        }
    }

    private boolean add(int a, int i, int j) {
        if (getTakenNumbers(i, j).contains(a)) return false;
        sudoku[i][j].number = a;
        sudoku[i][j].initial = true;
        return true;
    }

    private void paint(int a, int i, int j) {
        JPanel panel = board[i][j];
        JTextField jTextField = (JTextField) board[i][j].getComponent(0);
        jTextField.setFont(new Font("Lucida Grande", Font.PLAIN, 25));
        jTextField.setForeground(Color.gray);

        ActionListener task = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("T");
            }
        };
        Timer timer = new Timer(3000 , task);
        timer.setRepeats(false);
        timer.start();

        jTextField.setText("" + a);
        panel.revalidate();
        panel.repaint();
    }

    private void erase(int i, int j) {
        JTextField jTextField = (JTextField) board[i][j].getComponent(0);
        jTextField.setText("");
        board[i][j].revalidate();
        board[i][j].repaint();
    }

    private HashSet<Integer> getTakenNumbers(int i, int j) {
        HashSet<Integer> takenNumbers = new HashSet<>();

        for (int k = 0; k < 9; k++) if (sudoku[i][k].number != 0 && k != j) takenNumbers.add(sudoku[i][k].number);
        for (int k = 0; k < 9; k++) if (sudoku[k][j].number != 0 && k != i) takenNumbers.add(sudoku[k][j].number);

        int bigBoxRow = 0;
        int bigBoxColumn = 0;
        if (i <= 5 && i > 2) bigBoxRow = 3;
        if (i <= 8 && i > 5) bigBoxRow = 6;
        if (j <= 5 && j > 2) bigBoxColumn = 3;
        if (j <= 8 && j > 5) bigBoxColumn = 6;

        for (int k = bigBoxRow; k < bigBoxRow + 3; k++) for (int l = bigBoxColumn; l <  bigBoxColumn + 3; l++) if (sudoku[k][l].number != 0 && k != i && l != j) takenNumbers.add(sudoku[k][l].number);

        return takenNumbers;
    }
}



import java.util.Stack;
public class Box {

    public int number = 0;
    public int i, j;
    public Stack possibles = new Stack();
    public Box back;
    public boolean initial = false;

    public Box(int i, int j) {
        this.i = i;
        this.j = j;
    }

    public Box() {}
}
import javax.swing.*;
导入javax.swing.Timer;
导入java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.*;
导入java.util.Stack;
公共级SudokuApp{
私有JFrame;
int i=9;
int j=9;
JPanel[]董事会=新JPanel[i][j];
JButton nextButton=新JButton(“解析器”);
Box[][]数独=新Box[9][9];
Box newCurrent=newbox();
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
公开募捐{
试一试{
SudokuApp window=新的SudokuApp();
window.frame.setVisible(true);
}捕获(例外e){
e、 printStackTrace();
}
}
});
}
公共SudokuApp(){
初始化();
}
私有void初始化(){
frame=新的JFrame();
frame.setTitle(“数独解算器”);
框架.立根(100100510555);
frame.setLocationRelativeTo(空);
frame.setresizeable(false);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel面板=新的JPanel();
frame.getContentPane().add(面板,BorderLayout.CENTER);
panel.setLayout(新网格布局(i,j));
//发起董事会
对于(int m=0;m对于(int k=1;k您需要更改程序的结构。具体地说,您将希望摆脱solve方法中的嵌套while循环,而代之以单个Swing计时器。该计时器将重复9*9次,并在其内部有一个计数器字段,您将希望在其内部执行当前的代码在嵌套的while循环中执行

它可能看起来像

    // TIMER_DELAY could be 2000 if you want a 2 second delay
    new Timer(TIMER_DELAY, new ActionListener() {
        private int i = 0;
        private int j = 0; 

        @Override
        public void actionPerformed(ActionEvent e) {
            // MAX_ROWS is 9
            if (i == MAX_ROWS) {
                // we've iterated through the whole thing
                ((Timer) e.getSource()).stop();
            }
            if (j == MAX_ROWS) {
                // we've gone through all the columns
                i++;    // the next row
                j = 0;  // start at column 0
            }
            // TODO the code in the nested while loop.

            j++;
        }
    }).start();
例如,一个功能性程序将文本延迟放置在字段中(但不能解决任何问题):

导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Font;
导入java.awt.GridLayout;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.*;
公共类SudokuMCVE扩展了JPanel{
私有静态final int CLUSTER=3;
私有静态最终int MAX_行=9;
专用静态最终浮点字段_PTS=32f;
专用静态最终内部间隙=3;
专用静态最终颜色BG=Color.BLACK;
私有静态最终颜色已解决\u BG=Color.LIGHT\u GRAY;
公共静态最终整数定时器延迟=2*1000;
私有JTextField[][]fieldGrid=新JTextField[MAX_ROWS][MAX_ROWS];
公共SudokuMCVE(){
JPanel主面板=新JPanel(新网格布局(集群,集群));
mainPanel.setBorder(BorderFactory.createEmptyByOrder(间隙,间隙,间隙));
主面板立根接地(BG);
JPanel[][]面板=新的JPanel[集群][集群];
对于(int i=0;iimport java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class SudokuMCVE extends JPanel {
    private static final int CLUSTER = 3;
    private static final int MAX_ROWS = 9;
    private static final float FIELD_PTS = 32f;
    private static final int GAP = 3;
    private static final Color BG = Color.BLACK;
    private static final Color SOLVED_BG = Color.LIGHT_GRAY;
    public static final int TIMER_DELAY = 2 * 1000;
    private JTextField[][] fieldGrid = new JTextField[MAX_ROWS][MAX_ROWS];

    public SudokuMCVE() {
        JPanel mainPanel = new JPanel(new GridLayout(CLUSTER, CLUSTER));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        mainPanel.setBackground(BG);
        JPanel[][] panels = new JPanel[CLUSTER][CLUSTER];
        for (int i = 0; i < panels.length; i++) {
            for (int j = 0; j < panels[i].length; j++) {
                panels[i][j] = new JPanel(new GridLayout(CLUSTER, CLUSTER, 1, 1));
                panels[i][j].setBackground(BG);
                panels[i][j].setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
                mainPanel.add(panels[i][j]);
            }
        }

        for (int row = 0; row < fieldGrid.length; row++) {
            for (int col = 0; col < fieldGrid[row].length; col++) {
                fieldGrid[row][col] = createField(row, col);
                int i = row / 3;
                int j = col / 3;
                panels[i][j].add(fieldGrid[row][col]);
            }
        }

        setLayout(new BorderLayout());
        add(mainPanel, BorderLayout.CENTER);
        add(new JButton(new SolveAction("Solve")), BorderLayout.PAGE_END);
    }

    private JTextField createField(int row, int col) {
        JTextField field = new JTextField(2);
        field.setHorizontalAlignment(JTextField.CENTER);
        field.setFont(field.getFont().deriveFont(Font.BOLD, FIELD_PTS));

        return field;
    }

    private class SolveAction extends AbstractAction {

        public SolveAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            new Timer(TIMER_DELAY, new ActionListener() {
                private int i = 0;
                private int j = 0;

                @Override
                public void actionPerformed(ActionEvent e) {
                    // MAX_ROWS is 9
                    if (i == MAX_ROWS) {
                        ((Timer) e.getSource()).stop();
                    }
                    if (j == MAX_ROWS) {
                        i++;
                        j = 0;
                    }
                    int number = (int) (MAX_ROWS * Math.random()) + 1;
                    fieldGrid[i][j].setBackground(SOLVED_BG);
                    fieldGrid[i][j].setText(String.valueOf(number));

                    j++;
                }
            }).start();
        }
    }

    private static void createAndShowGui() {
        SudokuMCVE mainPanel = new SudokuMCVE();

        JFrame frame = new JFrame("SudokuMCVE");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            createAndShowGui();
        });
    }
}