2013-06-05 75 views
0

我正在开发一个程序,以使用swing gui在java中生成和解决数独谜题。我在使用JTextField上的.setText()方法时出现问题,但文本未更新。JAVA SWING:无法更改JTextField的文本

这里是我的代码:

主类:

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]); 

我没有收到任何错误信息,但它没有更新的文字。我尝试用“Z”替换数据[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}; 

但是在你的构造函数,你重新inistalition他们(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小号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); 

    } 
+0

谢谢,我错过了。我添加了“x ++;”在setText()之后。但是没有解决问题。 – Petefic

+0

见更新,你的阴影'data'参数) – MadProgrammer

+0

修正阴影问题,好,谢谢。不知道我在想什么。尽管如此,仍然没有解决问题。我修正了我的主要帖子。 – Petefic

-2

通话setText()只更新型号JTextField。换句话说,JTextField存储一个内部字符串与您发送它的值。然而,视图(即屏幕上显示的内容)是而不是已更新。这实际上是一件好事,因为绘画很慢。如果每次在Sudoku程序中调用setText()时都更新UI,则需要更新81次。

您可以在任何Component的子类上调用invalidate()来强制更新视图。在你的情况下,你可能应该在主要的JFrameJPanel上打电话invalidate(),其中包含你所有的JTextField。这将导致GUI刷新一次,而不是之前提到的81次。

P.S.有关更多信息,我建议您研究模型 - 视图 - 控制器设计模式。

+1

首先,'RepaintManager'巩固重绘请求分解成尽可能少的通话越好,这样你就可以调用'repaint'因为往往你喜欢和'RepaintManager'将决定何时以及有多少是会得到重新绘制。其次,即使在最简单的测试中,我也不确定你的答案是否成立,因此调用'setText'将立即在屏幕上更新(几乎)...'invalidate'只处理组件的布局,它是一个它被绘的副作用。 – MadProgrammer

+0

@MadProgrammer Gah!我混淆了使用'invalidate()'...在我回答这些问题之前,我需要研究它。 –