2013-06-05 77 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()'...在我回答這些問題之前,我需要研究它。 –