简体   繁体   English

JAVA SWING:无法更改JTextField的文本

[英]JAVA SWING: Unable to change text of JTextField

I am working on a program to generate and solve sudoku puzzles in java using a swing gui. 我正在开发一个使用swing gui在java中生成和解决数独难题的程序。 I am having a problem where I use the .setText() method on a JTextField but the text is not updated. 我在JTextField上使用.setText()方法时遇到问题,但文本未更新。

Here is my code: 这是我的代码:

main class: 主类:

package sudoku;

public class SudokuSolver {

    public static void main(String[] args) {

        GUI gui = new GUI();
        gui.setVisible(true);

    }

}

GUI class: 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);

    }

}

Board class: 董事会班:

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 class: 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++;

            }
        }
    }

}

I also have another class called Puzzle where there is a generate() and a solve() method that both return int[][]. 我还有另一个名为Puzzle的类,其中有一个generate()和solve()方法都返回int [] []。 I don't believe anything in it is relevant to the problem so I'm omitting it for space. 我不相信其中任何与问题有关的东西,因此我省去了空间。

The problem is with this line is the BoardSection class: 问题是此行是BoardSection类:

fields[x].setText(data[i][j]);

I am not getting any error messages, however it is not updating the text. 我没有收到任何错误消息,但是它没有更新文本。 I tried replacing data[i][j] with "Z" to see if the problem was the data I was passing but it still doesn't work with just a simple string. 我尝试将数据[i] [j]替换为“ Z”,以查看问题是否出在我传递的数据上,但仅使用简单的字符串仍然无法解决问题。 I did however try putting the following line in the for loop that is inside the BoardSection constructor method and it DID display. 但是,我确实尝试将以下行放入BoardSection构造函数方法内的for循环中,并对其进行DID显示。

fields[i].setText("0");

Can anyone explain why it works in the constructor but not when the fillSection() method is called? 谁能解释为什么它在构造函数中起作用,但是当fillSection()方法被调用时却不能解释吗?

Do you mean to only ever fill the first field? 您是说只填写第一个字段吗? You never update the x variable to anything other the 0 ? 您永远不会将x变量更新为0以外的任何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]);
        }
    }
}

You could try... 你可以尝试...

fields[i * j].setText(data[i][j]);

Or actually modify the x parameter accordingly... 或者实际上相应地修改x参数...

Updated... 更新...

The other problem you're having is your shadowing the data variable been passed to your fillSection method... 您遇到的另一个问题是将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];
    //...
}

Updated... 更新...

Don't know if this is related or not, but it's still a problem... 不知道这是否相关,但这仍然是一个问题...

You're String comparison is wrong... == is check to see if the two objects share the same memory space, which is never going to be true for String (in this manner) 您是String比较是错误的... ==正在检查两个对象是否共享相同的内存空间,这对于String永远是不正确的(以这种方式)

if (cmd == "Generate") {

Instead, you should be using String#equals to compare the contents of the objects... 相反,您应该使用String#equals来比较对象的内容...

if ("Generate".equals(cmd)) {

This would mean that the puzz is never been updated, so when you pass it to your fields, it is probably blank... 这意味着该puzz永远不会更新,因此当您将其传递到字段时,它可能是空白的...

Updated... 更新...

Yet another issue ;) 另一个问题;)

In your Board class, you are defining 9 board sections... 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};

But in you constructor, you are re-inistalition them (within in the sections array)... 但是在构造函数中,您需要重新创建它们(在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]);
    }

}

This means that the BoardSection s nw , etc are never actually added to the screen... 这意味着BoardSection s nw等实际上从未添加到屏幕上。

Instead, you should simply drop those sections and use the array directly... 相反,您只需删除这些部分并直接使用数组即可。

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

    }

Calling setText() only updates the model for the JTextField . 调用setText()仅更新JTextField模型 In other words, the JTextField stores an internal String with the value which you sent it. 换句话说, JTextField存储一个内部String以及您发送它的值。 However, the view (ie what is shown on your screen) is not updated. 但是, 视图 (即屏幕上显示的内容) 不会更新。 This is actually a good thing because painting is quite slow. 这实际上是一件好事,因为绘画速度很慢。 If the UI was updated every time you call setText() in your Sudoku program, it would have to update 81 times. 如果每次在Sudoku程序中调用setText()时都更新了UI,则它必须更新81次。

You can force the view to update by calling invalidate() on any subclass of Component . 您可以通过在Component任何子类上调用invalidate()来强制更新视图。 In your situation, you probably should call invalidate() on the main JFrame or the JPanel that contains all of your JTextField s. 在您的情况下,您可能应该在包含所有JTextField的主JFrameJPanel上调用invalidate() This will cause the GUI to refresh once, rather than the 81 times mentioned before. 这将导致GUI刷新一次,而不是之前提到的81次。

PS For more information, I suggest you research the Model-View-Controller design pattern. PS有关更多信息,建议您研究Model-View-Controller设计模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM