我正在开发一个使用swing gui在java中生成和解决数独谜题的程序。我遇到一个问题,我在JTextField上使用.setText()方法,但文本没有更新。
这是我的代码:
主要课程:
package sudoku;
public class SudokuSolver {
public static void main(String[] args) {
GUI gui = new GUI();
gui.setVisible(true);
}
}
GUI类:
package sudoku;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.Window.Type;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUI extends JFrame implements ActionListener {
private JPanel contentPane;
private Puzzle puzzle = new Puzzle();
private Board board = new Board();
private int[][] puzz = new int[9][9];
// GUI Constructor
public GUI() {
// set up window
setResizable(false);
setTitle("Sudoku Solver");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 300, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
// set up button panel
JPanel buttons = new JPanel();
contentPane.add(buttons, BorderLayout.SOUTH);
// set up generate button
JButton genButton = new JButton("Generate");
genButton.setMnemonic('g');
buttons.add(genButton);
genButton.addActionListener(this);
// set up solve button
JButton solveButton = new JButton("Solve");
solveButton.setMnemonic('s');
buttons.add(solveButton);
solveButton.addActionListener(this);
// set up board
contentPane.add(board, BorderLayout.CENTER);
}
// Button listener
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd == "Generate") {
// generate puzzle
puzz = puzzle.generate();
} else if (cmd == "Solve") {
// solve puzzle
puzz = puzzle.solve(puzz);
}
// display puzzle on the board
board.fill(puzz);
}
}
董事会成员:
package sudoku;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
public class Board extends JPanel {
// 9x9 board sections
private BoardSection nw = new BoardSection();
private BoardSection n = new BoardSection();
private BoardSection ne = new BoardSection();
private BoardSection w = new BoardSection();
private BoardSection c = new BoardSection();
private BoardSection e = new BoardSection();
private BoardSection sw = new BoardSection();
private BoardSection s = new BoardSection();
private BoardSection se = new BoardSection();
// array of sections
private BoardSection[] sections = { nw, n, ne, w, c, e, sw, s, se };
// Board Constructor
public Board() {
// 3x3 grid layout
setLayout(new GridLayout(3, 3));
// border
setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
// add board sections to board
for (int i = 0; i < sections.length; i++) {
sections[i] = new BoardSection();
add(sections[i]);
}
}
// fill the board with data
public void fill(int[][] data) {
// create data sections
String[][] nwData = new String[3][3];
String[][] nData = new String[3][3];
String[][] neData = new String[3][3];
String[][] wData = new String[3][3];
String[][] cData = new String[3][3];
String[][] eData = new String[3][3];
String[][] swData = new String[3][3];
String[][] sData = new String[3][3];
String[][] seData = new String[3][3];
// break data into data sections
nwData = createSection(data, 0, 0);
nData = createSection(data, 3, 0);
neData = createSection(data, 6, 0);
wData = createSection(data, 0, 3);
cData = createSection(data, 3, 3);
eData = createSection(data, 6, 3);
swData = createSection(data, 0, 6);
sData = createSection(data, 3, 6);
seData = createSection(data, 6, 6);
// fill board section with data section
nw.fillSection(nwData);
n.fillSection(nData);
ne.fillSection(neData);
w.fillSection(wData);
c.fillSection(cData);
e.fillSection(eData);
sw.fillSection(swData);
s.fillSection(sData);
se.fillSection(seData);
}
// split data into 3x3 section with 0,0 starting at x, y then convert to
// string
private String[][] createSection(int[][] data, int x, int y) {
int[][] intSection = new int[3][3];
String[][] strSection = new String[3][3];
// break into section
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
intSection[i][j] = data[i + x][j + y];
}
}
// convert section to string
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
strSection[i][j] = Integer.toString(intSection[i][j]);
}
}
return strSection;
}
}
BoardSection类:
package sudoku;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.BorderFactory;
public class BoardSection extends JPanel {
// each square
private JTextField nw = new JTextField();
private JTextField n = new JTextField();
private JTextField ne = new JTextField();
private JTextField w = new JTextField();
private JTextField c = new JTextField();
private JTextField e = new JTextField();
private JTextField sw = new JTextField();
private JTextField s = new JTextField();
private JTextField se = new JTextField();
// array of the squares
private JTextField[] fields = new JTextField[] { nw, n, ne, w, c, e, sw, s,
se };
// Board Section Constructor
public BoardSection() {
// 3x3 grid layout
setLayout(new GridLayout(3, 3));
// border
setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
// add all fields to the board section
for (int i = 0; i < fields.length; i++) {
fields[i] = new JTextField(1);
fields[i].setHorizontalAlignment(JTextField.CENTER);
fields[i].setEditable(false);
add(fields[i]);
}
}
// Display the data on the board
public void fillSection(String[][] data) {
int x = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
fields[x].setText(data[i][j]);
x++;
}
}
}
}
我还有另一个名为Puzzle的类,其中有一个generate()和一个solve()方法,它们都返回int [] []。我不相信它中的任何内容与问题有关,所以我在空间中省略它。
问题在于这一行是BoardSection类:
fields[x].setText(data[i][j]);
我没有收到任何错误消息,但是它没有更新文本。我尝试用&#34; Z&#34;替换数据[i] [j]。看问题是否是我传递的数据,但它仍然不能只使用一个简单的字符串。但是我确实尝试将以下行放在BoardSection构造函数方法内部的for循环中并显示DID。
fields[i].setText("0");
任何人都可以解释为什么它在构造函数中有效但在调用fillSection()方法时却没有吗?
答案 0 :(得分:3)
你的意思是只填充第一个字段吗?您永远不会将x
变量更新为0
的其他任何内容吗?
public void fillSection(String[][] data) {
data = new String[3][3];
int x = 0; // This never changes?
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
fields[x].setText(data[i][j]);
}
}
}
你可以试试......
fields[i * j].setText(data[i][j]);
或者实际相应地修改x
参数......
<强>更新... 强>
您遇到的另一个问题是data
变量传递给您的fillSection
方法的阴影......
public void fillSection(String[][] data) {
// Oh look, I've overridden every thing
// you just gave with my own copy of the data!!
data = new String[3][3];
//...
}
<强>更新... 强>
不知道这是否相关,但它仍然是一个问题......
您String
比较错误... ==
检查两个对象是否共享相同的内存空间,String
永远不会出现这种情况(以这种方式)
if (cmd == "Generate") {
相反,您应该使用String#equals
来比较对象的内容......
if ("Generate".equals(cmd)) {
这意味着puzz
永远不会更新,因此当您将其传递到您的字段时,它可能是空白的......
<强>更新... 强>
又一个问题;)
在Board
课程中,您要定义9个电路板部分......
private BoardSection nw = new BoardSection();
private BoardSection n = new BoardSection();
private BoardSection ne = new BoardSection();
private BoardSection w = new BoardSection();
private BoardSection c = new BoardSection();
private BoardSection e = new BoardSection();
private BoardSection sw = new BoardSection();
private BoardSection s = new BoardSection();
private BoardSection se = new BoardSection();
// array of sections
private BoardSection[] sections = {nw, n, ne, w, c, e, sw, s, se};
但是在你的构造函数中,你重新对它们进行了修改(在sections
数组中)......
// Board Constructor
public Board() {
//...//
// add board sections to board
for (int i = 0; i < sections.length; i++) {
// Look ma, new Board!!
sections[i] = new BoardSection();
add(sections[i]);
}
}
这意味着BoardSection
s nw
等从未实际添加到屏幕上......
相反,你应该简单地删除这些部分并直接使用数组......
public class Board extends JPanel {
// array of sections
private BoardSection[] sections;
// Board Constructor
public Board() {
//...//
// add board sections to board
sections = new BoardSection[9];
for (int i = 0; i < sections.length; i++) {
sections[i] = new BoardSection();
add(sections[i]);
}
}
// fill the board with data
public void fill(int[][] data) {
// create data sections
String[][] nwData = new String[3][3];
String[][] nData = new String[3][3];
String[][] neData = new String[3][3];
String[][] wData = new String[3][3];
String[][] cData = new String[3][3];
String[][] eData = new String[3][3];
String[][] swData = new String[3][3];
String[][] sData = new String[3][3];
String[][] seData = new String[3][3];
// break data into data sections
nwData = createSection(data, 0, 0);
nData = createSection(data, 3, 0);
neData = createSection(data, 6, 0);
wData = createSection(data, 0, 3);
cData = createSection(data, 3, 3);
eData = createSection(data, 6, 3);
swData = createSection(data, 0, 6);
sData = createSection(data, 3, 6);
seData = createSection(data, 6, 6);
// fill board section with data section
sections[0].fillSection(nwData);
sections[1].fillSection(nData);
sections[2].fillSection(neData);
sections[3].fillSection(wData);
sections[4].fillSection(cData);
sections[5].fillSection(eData);
sections[6].fillSection(swData);
sections[7].fillSection(sData);
sections[8].fillSection(seData);
}
答案 1 :(得分:-2)
调用setText()
只会更新JTextField
的模型。换句话说,JTextField
存储一个内部String,其中包含您发送它的值。但是,视图(即屏幕上显示的内容)未更新。这实际上是一件好事,因为绘画很慢。如果每次在Sudoku程序中调用setText()
时都会更新UI,则必须更新81次。
您可以通过在invalidate()
的任何子类上调用Component
来强制更新视图。在您的情况下,您可能应该在主invalidate()
或包含所有JFrame
的{{1}}上致电JPanel
。这将导致GUI刷新一次,而不是之前提到的81次。
P.S。有关更多信息,我建议您研究模型 - 视图 - 控制器设计模式。