为Sudoku解算器构建GUI(使用ASCII示例完成) [英] Building a GUI for a Sudoku Solver (Complete with ASCII Example)

查看:144
本文介绍了为Sudoku解算器构建GUI(使用ASCII示例完成)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,

我创建了一个基本的数独求解器,可以很快解决大多数问题。我仍然需要做很多工作才能解决最棘手的问题,但我想先尝试实现一个基本的JFrame GUI。

I have created a basic Sudoku solver that can solve most problems fairly quickly. I still have a lot of work ahead of me to make it solve even the hardest problems, but I'd like to try to implement a basic JFrame GUI first.

I曾经使用互联网小程序,但从未使用过JFrame。

I have worked with internet applets in the past, but never before with JFrames.

我想创建类似于下图的图像(对于初学者):

I want to create something similar to the image below (for starters):

-------------------------------------------------------------------------------------------------
! Sudoku Solver 1.0                                                                      - [] X !
-------------------------------------------------------------------------------------------------
!  _____________ _____________ _____________         _____________ _____________ _____________  !
! |  _   _   _  |  _   _   _  |  _   _   _  |       |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !5! !_! !_! | !_! !_! !_! | !6! !_! !1! |       | !5! !7! !2! | !4! !9! !3! | !6! !8! !1! | !
! |  _   _   _  |  _   _   _  |  _   _   _  |       |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !6! !_! !_! | !_! !_! !2! | !4! !_! !_! |       | !6! !1! !3! | !8! !5! !2! | !4! !7! !9! | !
! |  _   _   _  |  _   _   _  |  _   _   _  |       |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !_! !_! !_! | !7! !_! !1! | !_! !_! !2! |       | !8! !4! !9! | !7! !6! !1! | !3! !5! !2! | !
! -_____________-_____________-_____________-       -_____________-_____________-_____________- !
! |  _   _   _  |  _   _   _  |  _   _   _  |       |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !_! !_! !4! | !_! !2! !_! | !_! !3! !_! |       | !1! !6! !4! | !9! !2! !7! | !5! !3! !8! | !
! |  _   _   _  |  _   _   _  |  _   _   _  | .---. |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !_! !3! !_! | !_! !_! !_! | !_! !9! !_! | | > | | !2! !3! !8! | !5! !1! !6! | !7! !9! !4! | !
! |  _   _   _  |  _   _   _  |  _   _   _  | '---' |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !_! !_! !_! | !_! !4! !_! | !_! !_! !_! |       | !7! !9! !5! | !3! !4! !8! | !1! !2! !6! | !
! -_____________-_____________-_____________-       -_____________-_____________-_____________- !
! |  _   _   _  |  _   _   _  |  _   _   _  |       |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !_! !2! !_! | !1! !_! !5! | !9! !_! !_! |       | !4! !2! !7! | !1! !8! !5! | !9! !6! !3! | !
! |  _   _   _  |  _   _   _  |  _   _   _  |       |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !_! !_! !_! | !6! !_! !_! | !_! !_! !5! |       | !3! !8! !1! | !6! !7! !9! | !2! !4! !5! | !
! |  _   _   _  |  _   _   _  |  _   _   _  |       |  _   _   _  |  _   _   _  |  _   _   _  | !
! | !_! !_! !6! | !_! !3! !_! | !_! !_! !7! |       | !9! !5! !6! | !2! !3! !4! | !8! !1! !7! | !
! -_____________-_____________-_____________-       -_____________-_____________-_____________- !
!                                                                                               !
! .-------------------------------------------------------------------------------------------. !
! |                                                                                           | !
! |               Solved Puzzle in 9.096ms      |      Completely Solved: True                | !
! |                                                                                           | !
! '-------------------------------------------------------------------------------------------' !
!                                                                                               !
-------------------------------------------------------------------------------------------------

:左拼图


  • 9x9应明确定义章节(两者之间的行;单独的方框)

  • 文本框应该只接受数字/只允许输入一个数字(如果可能)

:正确拼图


  • 9x9应明确定义部分(两者之间的行;单独的框)

  • 如果可以/不能编辑框,只要它们可以显示结果就没关系

:按钮在中心


  • 应该运行[SudokuPuzzle] .solve();

:底部文本框


  • 不可编辑

我从过去的经历中了解到那个是可以在JFrame中完成,但由于我自己从未构建过一个,我不太确定哪个组件(内容项,面板,设置等)我需要使用它来满足我的规范。我还没有找到一种方法将文本框限制为数字,并阻止用户一次插入多个值。文本框真的是最好的选择,还是我错过了一些更符合我需求的东西?

I know from past experiences that this can all be done in a JFrame, but because I have never built one myself, I'm not quite sure which components (content items, panels, settings, etc) I need to use to meet my specifications. I have yet to find a way to limit my text boxes to numbers and prevent the user from inserting more than one value at a time. Are text boxes really the best option, or am I missing something that can more specifically suit my needs?

我不仅需要知道我需要哪些课程,还要知道如何组织这些,使按钮在两个谜题之间保持舒适,文本框位于下方。从我阅读 MigLayout 似乎是一个简化此过程的选项。

I not only need to know which classes I need, but also how to organize these so that the button stays comfortably between the two puzzles and the text box sits underneath. From what I've read, MigLayout seems like an option to simplify this process.

很多,非常感谢任何帮助过的人。如果这个问题的任何部分显得有些粗鲁或突然,我道歉。我倾向于在晚上发布我的大部分问题,所以在我尝试所有回复之前,社区有几个小时的时间来仔细研究它(事实上我大部分时间都在做这些事情)。

Many, many thanks to anyone who helps. If any part of this question appears a little rude or abrupt, I apologize. I tend to post most of my questions at night, so the community has a few hours to mull it over before I try all the responses (that and the fact that I'm out doing stuff most days).

我会在1-2小时内醒来回答任何问题。

I will be awake for 1-2 more hours to answer any questions.

再次感谢,

Justian

推荐答案

Sudoku GUI



好吧,我忍不住了...这是我的尝试。它全部在一个包中:

The Sudoku GUI

Ok, I couldn't help myself... Here is my try. It's all in one package:


  • 所有元素符合规范的GUI(问题)

  • 灵活布局

  • 没有外部依赖关系 - 使用标准Swing布局

  • 输入验证(仅数字0-9)

  • 模型视图控制器架构

  • 后台任务运行器(您的GUI永远不会冻结)

  • 内置一些调试方法(Sudoku作为文本输出)

  • 虚拟实现 - 模拟显示GUI响应的长时间运行计算

  • GUI with all elements conforming specification (question)
  • flexible layout
  • no external dependencies - standard Swing layouts used
  • input validation (only digits 0-9)
  • Model View Controller architecture
  • background task runner (Your GUI never freezes)
  • some debugging methods built-in (output of Sudoku as text)
  • dummy implementation - simulates long running computation showing GUI responsiveness

我尽力制作代码尽我所能。可能有相当不清楚的部分。可能螺纹部分不清晰,但如果有人发现这有任何用处,我会很乐意更好地描述它。

I tried my best to make the code as readable as I could. There might be rather unclear parts. Probably the threading part isn't lucid, but if anyone finds this of any use I'd be glad to describe it better.

所以我的目标是最简单的用法。如果你看一下界面,很难打破这些东西(冻结UI,得到Null Pointer Exc等)作为编写公共API的练习。这可能不是最好的实现,但它是我写的最好的之一。 :)

So my aim was the simplest possible usage. If You look at the interfaces it's really hard to break this stuff (froze UI, get Null Pointer Exc etc.) as an exercise in writing public API's. This may not the best implementation, but It's one of the best I wrote. :)

希望有所帮助。

以下是它的样子:
运行示例http://a.imageshack.us/img256/754/sudokusolvergui.png

(注意:值是随机的)

所有你要做的就是实现界面:

All You have to do is implement the interface:

public interface SudokuImplementation {

    void goButtonPressed(Integer[][] leftSudokuValues, SudokuController resultAcceptor);
}

只需在此方法中执行所有计算并使用 resultAcceptor.setSudokuResult()

Just do all computation in this method and store results with resultAcceptor.setSudokuResult()

以下是实际显示GUI的方法:

Here is how to actually show GUI:

    SudokuImplementation sudokuImplementation =
        new YourSuperSudoku(); // <- your implementation

    SudokuView sudokuView = new SudokuView();
    sudokuView.setSudokuImplementation(sudokuImplementation);
    sudokuView.setVisible(true);

这就是全部!

所有类都在默认包中 - 您希望重构。以下是它们的列表:

All classes are in default package - refactor as You wish. Here is list of them:


  1. SudokuView - 主GUI

  2. SudokuRun - 示例跑步者

  3. SudokuController - 允许以安全的方式控制视图

  4. SudokuImplementation - 数独实现的接口

  5. DummySudokuImplementation - 示例实施

  1. SudokuView - main GUI
  2. SudokuRun - example runner
  3. SudokuController - allows to control the view in a safe manner
  4. SudokuImplementation - interface to sudoku implementation
  5. DummySudokuImplementation - example implementation



1.SudokuView:



1.SudokuView:

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.border.*;
/**
 * View which constructs every component and creates it's own controller.
 */
public class SudokuView extends JFrame {

    SudokuController controller;

    public void setSudokuImplementation(SudokuImplementation listener) {
        controller.setListener(listener);
    }

    /** Creates new form NewJFrame */
    public SudokuView() {
        controller = new SudokuController();
        setTitle("Sudoku Solver 1.0");
        getContentPane().add(createCenterPanel(), BorderLayout.CENTER);
        getContentPane().add(createBottomPanel(), BorderLayout.SOUTH);
        setMinimumSize(new Dimension(600, 300));
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private JPanel createBottomPanel() {
        JPanel bottomPanel = new JPanel(new GridBagLayout());
        JLabel leftLabel = createLabel("left");
        JLabel rightLabel = createLabel("right");

        controller.bindLeftLabel(leftLabel);
        controller.bindRightLabel(rightLabel);

        bottomPanel.add(leftLabel, getWholeCellConstraints());
        bottomPanel.add(new JSeparator(JSeparator.VERTICAL));
        bottomPanel.add(rightLabel, getWholeCellConstraints());

        bottomPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
        return bottomPanel;
    }

    private JLabel createLabel(String text) {
        JLabel label = new JLabel(text);
        label.setHorizontalAlignment(JLabel.CENTER);
        return label;
    }

    private JPanel createCenterPanel() {
        JPanel centerPanel = new JPanel(new GridBagLayout());
        centerPanel.add(createLeftPanel(), getWholeCellConstraints());
        centerPanel.add(createCenterButton(), getPreferredSizeConstraint());
        centerPanel.add(createRightPanel(), getWholeCellConstraints());
        return centerPanel;
    }

    private GridBagConstraints getPreferredSizeConstraint() {
        // default will do
        return new GridBagConstraints();
    }

    private JButton createCenterButton() {
        JButton goButton = new JButton(">");
        controller.bindCenterButton(goButton);
        return goButton;
    }
    private static final Insets sixPixelInset = new Insets(6, 6, 6, 6);

    private JPanel createRightPanel() {
        JPanel rightPanel = create3x3Panel(6);
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                JPanel panel2 = create3x3Panel(2);
                fillPanelWithNonEditable(panel2, i, j);
                rightPanel.add(panel2);

            }
        }
        rightPanel.setBorder(new EmptyBorder(sixPixelInset));
        return rightPanel;
    }

    private JPanel createLeftPanel() {
        JPanel leftPanel = create3x3Panel(6);
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                JPanel panel2 = create3x3Panel(2);
                fillPanelWithEditable(panel2, i, j);
                leftPanel.add(panel2);

            }
        }
        leftPanel.setBorder(new EmptyBorder(sixPixelInset));
        return leftPanel;
    }

    private GridBagConstraints getWholeCellConstraints() {
        GridBagConstraints wholePanelCnstr = getPreferredSizeConstraint();
        wholePanelCnstr.fill = java.awt.GridBagConstraints.BOTH;
        wholePanelCnstr.weightx = 1.0;
        wholePanelCnstr.weighty = 1.0;
        return wholePanelCnstr;
    }

    private void fillPanelWithEditable(JPanel panel, int majorRow, int majorColumn) {
        for (int minorRow = 0; minorRow < 3; minorRow++) {
            for (int minorColumn = 0; minorColumn < 3; minorColumn++) {
                final JFormattedTextField editableField = createEditableField();
                int column = majorColumn * 3 + minorColumn;
                int row = majorRow * 3 + minorRow;
                controller.bindLeftSudokuCell(row, column, editableField);
                panel.add(editableField);
            }
        }
    }

    private void fillPanelWithNonEditable(JPanel panel, int majorRow, int majorColumn) {
        for (int minorRow = 0; minorRow < 3; minorRow++) {
            for (int minorColumn = 0; minorColumn < 3; minorColumn++) {
                final JFormattedTextField editableField = createNonEditableField();
                int column = majorColumn * 3 + minorColumn;
                int row = majorRow * 3 + minorRow;
                controller.bindRightSudokuCell(row, column, editableField);
                panel.add(editableField);
            }
        }
    }

    private JPanel create3x3Panel(int gap) {
        final GridLayout gridLayout = new GridLayout(3, 3, 1, 1);
        gridLayout.setHgap(gap);
        gridLayout.setVgap(gap);
        JPanel panel = new JPanel(gridLayout);
        return panel;
    }

    private JFormattedTextField createNonEditableField() {
        JFormattedTextField field = createEditableField();
        field.setEditable(false);
        field.setBackground(Color.WHITE); // otherwise non-editable gets gray
        return field;
    }

    private JFormattedTextField createEditableField() {
        JFormattedTextField field = new JFormattedTextField();
        // accept only one digit and nothing else
        try {
            field.setFormatterFactory(new DefaultFormatterFactory(new MaskFormatter("#")));
        } catch (java.text.ParseException ex) {
        }
        field.setPreferredSize(new Dimension(16, 30));
        field.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        field.setText(" ");
        field.setBorder(null);
        return field;
    }
}



2。 SudokuRun:



2. SudokuRun:

import java.awt.EventQueue;
import javax.swing.UIManager;

public class SudokuRun implements Runnable {

    public void run() {
        // ******************** here You can swap Your true implementation
        SudokuImplementation sudokuImplementation = new DummySudokuImplementation();
        // ***************************** *************** ********* **** ** *


        SudokuView sudokuView = new SudokuView();
        sudokuView.setSudokuImplementation(sudokuImplementation);
        sudokuView.setVisible(true);
    }

    public static void main(String args[]) {
        tryToSetSystemLookAndFeel();
        EventQueue.invokeLater(new SudokuRun());
    }

    private static void tryToSetSystemLookAndFeel() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ex) {
            System.out.println("Couldn't set LAF");
        }
    }
}



3。 SudokuController:



3. SudokuController:

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;

public class SudokuController {

    JLabel leftLabel, rightLabel;
    JFormattedTextField[][] leftSudoku, rightSudoku;
    JButton goButton;

    public SudokuController() {
        leftSudoku = new JFormattedTextField[9][9]; // standard sudoku size
        rightSudoku = new JFormattedTextField[9][9];
    }

    void bindLeftLabel(JLabel label) {
        leftLabel = label;
    }

    void bindRightLabel(JLabel label) {
        rightLabel = label;
    }

    void bindLeftSudokuCell(final int row, final int column, JFormattedTextField field) {
        field.addPropertyChangeListener("value", new PropertyChangeListener() {

            // if user edits field than You could do something about it here
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getNewValue() != null) {
                    String newValue = (String) evt.getNewValue();
                    userEditedValueAt(row, column, Integer.valueOf(newValue));
                }
            }
        });
        leftSudoku[row][column] = field;
    }

    void userEditedValueAt(int row, int column, int value) {
        System.out.println("Value changed at row:" + row + ", column:" + column + " to " + value);
    }

    void bindRightSudokuCell(int row, int column, JFormattedTextField field) {
        rightSudoku[row][column] = field;
    }

    void spitOutSudokus() {
        System.out.println("Left:");
        System.out.println(getPrettyPrinted(leftSudoku));
        System.out.println("Right:");
        System.out.println(getPrettyPrinted(rightSudoku));
    }

    private String getPrettyPrinted(JFormattedTextField[][] sudoku) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 9; i++) {
            sb.append("|");
            for (int j = 0; j < 9; j++) {
                if (sudoku[i][j] != null) {
                    sb.append(sudoku[i][j].getText());
                } else {
                    sb.append("-");
                }
                sb.append(" ");
            }
            sb.append("|\n");
        }
        return sb.toString();
    }

    void bindCenterButton(JButton goButton) {
        this.goButton = goButton;
        goButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                goButtonPressed();
            }
        });
    }
    SudokuImplementation listener;

    public void setListener(SudokuImplementation listener) {
        this.listener = listener;
    }
    Thread backGroundThread;

    private void goButtonPressed() {
        if (listener != null) {
            if (backGroundThread == null || (backGroundThread != null && !backGroundThread.isAlive())) {
                backGroundThread = new Thread() {

                    @Override
                    public void run() {
                        listener.goButtonPressed(getLeftValues(), SudokuController.this);
                    }
                };
                backGroundThread.start();
            }
        }
    }

    private Integer[][] getLeftValues() {
        Integer[][] values = new Integer[9][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (!leftSudoku[i][j].getText().equals(" ")) {
                    values[i][j] = Integer.valueOf(leftSudoku[i][j].getText());
                }
            }
        }
        return values;
    }

    public void setSudokuResult(final Integer[][] result) {
        // Any GUI interaction must be done on EDT
        // We don't want to block computation so we choose invokeLater
        // as opposed to invokeAndWait.
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                for (int i = 0; i < 9; i++) {
                    for (int j = 0; j < 9; j++) {
                        rightSudoku[i][j].setValue(String.valueOf(result[i][j]));
                    }
                }
            }
        });
    }

    public void setSudokuTime(final String time) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                leftLabel.setText("<html>Running time: <b>" + time);
            }
        });
    }

    public void setSudokuCompleted(final boolean completed) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {

                rightLabel.setText("<html>Completely Solved: <b>" + completed);
                if (completed) {
                    spitOutSudokus();
                }

            }
        });
    }
}



4。 SudokuImplementation:



4. SudokuImplementation:

public interface SudokuImplementation {

    void goButtonPressed(Integer[][] leftSudokuValues, SudokuController resultAcceptor);
}



5。 DummySudokuImplementation:



5. DummySudokuImplementation:

import java.util.concurrent.TimeUnit;

/**
 * Simulates Sudoku solver. Demonstrates how to update GUI. The whole
 * implementation is constructed so GUI never freezes.
 */
class DummySudokuImplementation implements SudokuImplementation {

    public DummySudokuImplementation() {
    }

    public void goButtonPressed(Integer[][] leftSudokuValues, SudokuController resultAcceptor) {
        System.out.println("Long running computation simulation...");
        for (int i = 0; i < 50; i++) {
            resultAcceptor.setSudokuCompleted(false);
            resultAcceptor.setSudokuTime(String.valueOf(i * 50) + "ms");
            resultAcceptor.setSudokuResult(getRandomResult());
            waitSomeTime();
        }
        resultAcceptor.setSudokuResult(leftSudokuValues);
        resultAcceptor.setSudokuCompleted(true);
        waitSomeTime();
        System.out.println("Done!");
    }

    private void waitSomeTime() {
        try {
            TimeUnit.MILLISECONDS.sleep(50);
        } catch (InterruptedException ex) {
        }
    }

    private Integer[][] getRandomResult() {
        Integer[][] randomResult = new Integer[9][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                randomResult[i][j] = (int) (Math.random() * 9);
            }
        }
        return randomResult;
    }
}



说明



我没有声称我的方式是最好的。我很乐意看到其他答案,比方说,用MigLayout完成的所有视图。这将非常有启发性。当Sun的实现只有一个时,我正在学习Swing GUI,因此它在我的风格中占了上风。也就是说,我建议咨询 Sun的Swing GUI短期课程。它还包括一个简单的研究案例。阅读之后,几乎整个SudokuView应该是清楚的。

Explanation

I don't claim that the way I did is the best. I'd love to see other answer with, let's say, all view done with MigLayout. It would be very instructive. I was learning Swing GUI when Sun's implementation were only one so it prevailed in my style. That said, I recommend consulting Sun's Swing GUI short course. It also includes a simple study case. After reading it almost whole part of SudokuView should be clear.

我确实将代码分开以使其更具可读性。这就是为什么控制器是另一个类,而不是视图的一部分。该视图仅用于构建小部件和布局,但为了简化(不创建更少的类),我还初始化控制器。

I did separate the code to make it more readable. That's why controller is another class, not part of view. The view is only for construction of widgets and layout, but to make it simple (not to create few more classes) I also initialize controller in it.

真正的工作是在控制器中。它包含了最毛茸茸的细节......线程也在那里,所以它实际上并没有那么明显。我从头开始实现了Thread类。还有另一种选择:使用 SwingWorker 。这可能是陈词滥调,但请说清楚:我使用线程随时对GUI做出响应。没有适当的线程,整个GUI会在计算发生时冻结。我决定从Sudoku的实现角度尽可能简单,就像非阻塞增量更新一样。

The real work is in the controller. It contains the hairiest details... Threading also goes there so it's not so obvious what it actually does. I implemented a Thread class from scratch. There is alternative: using SwingWorker. It might be a cliche, but make it clear: I use threading to make GUI responsive at any time. Without proper threading whole GUI would freeze when the computation would take place. I decided to make it as easy as possible from Sudoku's implementation point of view, like non-blocking incremental updates.

至于线程,知道运行哪个代码至关重要线。 GUI组件触发的每个操作都在EDT(事件调度线程)上运行。如果您对其执行任何长时间运行的任务,GUI将无法响应。所以我只是创建另一个线程(参见 goButtonPressed()的实现)并启动它。之后,EDT可以不受阻塞地处理任何其他事件。

As for threading it's crucial to know which code runs in which thread. Every action fired by GUI component runs on EDT (event dispatch thread). If you do any long-running task on it, the GUI won't be responsive. So I just make another thread (see implementation of goButtonPressed()) and start it. After that EDT can process any other events without blocking.

所以你的数独运行在一个特殊的后台线程中。它可以做任何想做的事情,除非它必须更新GUI。几乎可以肯定它会,因为这是部分更新的地方。这是一个问题:如果直接调用任何GUI组件(设置一些值),GUI将冻结。这是一种称为EDT调度违规的情况。所有与Swing的互动都应该在EDT上完成,以避免任何冻结。怎么做? EDT具有特殊的事件队列。您在队列上发布更新事件。在EDT代码上,不断观察传入事件并相应地更新GUI。所以基本上,它是后台线程和EDT之间的通信。在队列上发布事件您可以使用专为此设计的特殊实用程序方法: EventQueue.invokeLater(new Runnable(){/ *这里是您的GUI交互* /}); 。看一下 SudokuController 方法:

So Your Sudoku runs in a special, background thread. It can do whatever it wants, unless it has to update the GUI. It almost certain it will, since that's where partial updates go. Here's a catch: if You call any GUI component directly (set some values) than the GUI will freeze. This is a condition called EDT dispatch violation. All interaction with Swing should be done on EDT to avoid any freezes. How to do it? The EDT has special event queue just for that. You post an update event on the queue. On EDT code is constantly watching for incoming events and updates GUI accordingly. So basically, it's a communication between background thread and EDT. To post an event on the queue You could use special utility method designed just for this: EventQueue.invokeLater(new Runnable() { /* here goes your GUI interaction */ });. Take a look at SudokuController methods:


  • setSudokuResult()

  • public void setSudokuTime()

  • setSudokuCompleted()

那是GUI更新事件已发布。

That's were the GUI update events are posted.

这篇关于为Sudoku解算器构建GUI(使用ASCII示例完成)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆