JLabel 的 setText() 方法无法正常工作

JLabel's setText() method not working properly

我正在寻求解决 N-Queens 问题,并且我已经确定了我遇到的问题。有一个 JButton 被按下以在框架中以文本方式告诉用户他们的解决方案是否正确。这个按钮似乎只在 Queens 没有被放置在棋盘上时才起作用。问题似乎是我的 JLabel "ifNotSafe" 的 setText() 方法无法正常工作。如果我在该方法调用下放置打印语句,则正确的消息会发送到控制台,但标签不会更改。奇怪的是,该标签仅在 Queens 尚未放置在棋盘上时才有效。还有一个带有 x 值和 y 值的 Boxes 对象,每个对象都有一个 getter 方法。

import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;


 /*
* Overall class to make the whole ChessBoard and all the helper methods to 
* tell the user whether their solution is correct or not
*/
public class ChessBoardGUI extends JFrame {
    /**
 * 
 */
private static final long serialVersionUID = 1L;
//ImageIcon queenP = new //ImageIcon(getClass().getResource("/images/queen.png"));
//Image img = queenP.getImage();
//Image newImg = img.getScaledInstance(40, 40, java.awt.Image.SCALE_SMOOTH);
ImageIcon queenPic = new ImageIcon(newImg);
private static JButton tip;
private static JButton safe;
private static JLabel ifNotSafe;
private JButton[][] chessBoxes = new JButton[8][8];
public static JPanel chessBoard;
public static ArrayList<Boxes> queensOnBoard = new ArrayList<Boxes>();

/*
 * Makes the whole frame for the ChessBoard
 */
public ChessBoardGUI() {
    createBoard();
    createOtherThings();
    setSize(500, 500);

}

/*
 * Creates the Tip and Safe buttons And Label to display when the solution
 * is incorrect
 */
public void createOtherThings() {
    safe = new JButton("Safe?");
    tip = new JButton("Tip");
    ifNotSafe = new JLabel("Status of Board is displayed here...");

    ButtonListen1 safeListener = new ButtonListen1();
    ButtonListen2 tipListener = new ButtonListen2();

    safe.addActionListener(safeListener);
    tip.addActionListener(tipListener);

}

/*
 * ActionListener for the safe button
 */
class ButtonListen1 implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        // Tells user which queens are not safe
        if (checkSolution(queensOnBoard) == true) {
            //****THIS IS WHERE THE PROBLEM IS *******
            ifNotSafe.setText("This Solution is correct so far");
            System.out.println("Solution is correct");

        } else{
            ifNotSafe.setText("This Solution is incorrect so far");
            // *********Also highlight the queens that are not safe******
            System.out.println("Solution is incorrect");
        }
    }

}


/*
 * ActionListener for the tip button
 */
class ButtonListen2 implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        // ********Tells the user other places to put queens********
    }
}

/*
 * Creates the overall ChessBoard
 */
public void createBoard() {
    GridLayout gridLayout = new GridLayout();
    gridLayout.setRows(8);
    gridLayout.setColumns(8);
    chessBoard = new JPanel(gridLayout);
    chessBoard.setSize(400, 400);
    chessBoard.setBorder(new LineBorder(Color.BLACK));
    chessBoard.setVisible(true);

    /*
     * Loops through to add each chessBox to the chessBoard
     */
    for (int x = 0; x < 8; x++) {
        for (int y = 0; y < 8; y++) {
            chessBoxes[x][y] = new JButton();
            chessBoxes[x][y].setBorderPainted(false);
            /*
             * Assigns a color to every other box
             */
            if ((x + y) % 2 == 0) {
                chessBoxes[x][y].setBackground(Color.BLACK);
            } else {
                chessBoxes[x][y].setBackground(Color.WHITE);
            }
            chessBoxes[x][y].setOpaque(true);
            chessBoard.add(chessBoxes[x][y]);

            // Adds the ActionListener to each chessBox
            BoxListener boxListen = new BoxListener();
            chessBoxes[x][y].addActionListener(boxListen);
        }
    }
}

/*
 * Action Listener for if the individual boxes on the ChessBoard are clicked
 */
class BoxListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        JButton button = ((JButton) e.getSource());

        // Runs through a loop to find the X and Y coordinate of the
        // JButton(Box) that was clicked
        for (int x = 0; x < 8; x++) {
            for (int y = 0; y < 8; y++) {
                if (chessBoxes[x][y] == button) {
                    /*
                     * If there is No Queen at that JButton
                     */
                    if ((isOnBoard(queensOnBoard, x, y) == false)) {
                        // Makes sure the user can not place more than
                        // 8 Queens on the board
                        if (queensOnBoard.size() < 8) {
                            // Sets Picture of Queen on box
                            //button.setIcon(queenPic);
                     button.setText("Occupied");
                            // Adds box to the ArrayList of occupied boxes
                            queensOnBoard.add(new Boxes(x, y));
                        }
                    }
                    /*
                     * If there is a Queen at that JButton
                     */
                    else {
                        removeQueen(queensOnBoard, x, y);
                        //button.setIcon(null);
            button.setText("");
                    }
                }
            }
        }
    }
}

/*
 * Checks if a certain Box has a Queen in it or not
 * 
 * @param a Is the ArrayList of the Boxes currently occupied by Queens
 * 
 * @param x Is the X coordinate of the Box that was clicked
 * 
 * @param y Is the Y coordinate of the Box that was clicked
 */
public boolean isOnBoard(ArrayList<Boxes> a, int x, int y) {
    for (int i = 0; i < a.size(); i++) {
        if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
            return true;
        }
    }
    return false;
}

/*
 * Removes a Queen from the GUI at the specified Box (JButton)
 * 
 * @param a Is the ArrayList of the Boxes currently occupied by Queens
 * 
 * @param x Is the X coordinate of the Box that was clicked
 * 
 * @param y Is the Y coordinate of the Box that was clicked
 */
public void removeQueen(ArrayList<Boxes> a, int x, int y) {
    /*
     * Removes the box from the overall ArrayList of Boxes Occupied by
     * queens according to the x and y location
     */
    for (int i = 0; i < a.size(); i++) {
        if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
            queensOnBoard.remove(i);
        }
    }
}

/*
 * Return to the user which queens need to be highlighted
 * 
 * @param queensOnBoard Is the ArrayList of Boxes that are occupied by
 * Queens currently on the ChessBoard
 */
public void conflictingQueens(ArrayList<Boxes> queensOnBoard) {
    // *******Call the highlightBoxes method using the ArrayList
    // Of Boxes you get from this method

}

/*
 * Checks to see if solution is correct thusfar
 * 
 * @param queensOnBoard Is the ArrayList of Boxes that are occupied by
 * Queens currently on the ChessBoard
 */
public boolean checkSolution(ArrayList<Boxes> queensOnBoard) {
    int size = queensOnBoard.size();
    if (size < 1) {
        return true;
    }
    if (size == 1) {
        return true;
    }
    for (int x = 0; x < size - 1; x++) {
        for (int y = 1; y < size; y++) {
            // Checks if Queen is safe from horizontal attacks
            if (queensOnBoard.get(x).getX() == queensOnBoard.get(y).getX()) {
                return false;
                // Checks if Queen is safe from vertical attacks
            } else if (queensOnBoard.get(x).getY() == queensOnBoard.get(y).getY()) {
                return false;
                // Checks if Queen is safe from diagonal attacks
                // Uses diagonalAttack(queensOnBoard) as a helper method
            } // else if(){
                // return false;
                // }
        }
    }

    return true;
}

/*
 * Checks to see if the queen is safe from diagonal attacks
 * 
 *
 */
// public boolean diagonalAttack(ArrayList<Boxes> queensOnBoard){
 //********
// }

/*
 * Highlights boxes that are conflicting with one another
 * 
 * @param highlight Is the ArrayList of Boxes that are occupied by Queens
 * currently on the ChessBoard
 */
public void highlightBoxes(ArrayList<Boxes> highlight) {
    int size1 = highlight.size();
    int size2 = queensOnBoard.size();

    // When there aren't any queens at risk, this block
    // changes the background colors of the boxes back to
    // Their respective color
    if ((size1 == 0) && size1 == 1) {
        for (int x = 0; x < 8; x++) {
            for (int y = 0; y < 8; y++) {
                chessBoxes[x][y] = new JButton();
                chessBoxes[x][y].setBorderPainted(false);
                /*
                 * Assigns a color to every other box
                 */
                if ((x + y) % 2 == 0) {
                    chessBoxes[x][y].setBackground(Color.BLACK);
                } else {
                    chessBoxes[x][y].setBackground(Color.WHITE);
                }
            }
        }
    }

    // Runs through both the highlight and queensOnBoard ArrayLists and
    // changes the background for the Queens at risk
    for (int b = 0; b < size2; b++) {
        for (int a = 0; a < size1; a++) {
            if ((highlight.get(a).getX() == queensOnBoard.get(b).getX())
                    && (highlight.get(a).getY() == queensOnBoard.get(b).getY())) {
                int x = queensOnBoard.get(b).getX();
                int y = queensOnBoard.get(b).getY();
                chessBoxes[x][y].setBackground(Color.RED);
            }
        }
    }
}

/*
 * Main method to run the program
 * 
 * @param args Is the String of args given to the console to run the
 * operations of the program
 */
public static void main(String[] args) {
    JFrame frame = new ChessBoardGUI();
    frame.add(chessBoard);
    chessBoard.setLocation(50, 50);

    JPanel panel1 = new JPanel();
    panel1.add(ifNotSafe);
    panel1.add(safe);
    panel1.add(tip);


    frame.add(panel1);
    frame.setTitle("ChessBoard");
    frame.setVisible(true);
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}

}

您可能遇到布局问题,因为您的 JLabel 显示不正确,因为包含它的 JPanel 已错误地添加到 GUI。了解到JFrame的contentPane默认使用BorderLayout,所以在给它添加组件的时候,需要指定组件放置的BorderLayout位置,grid会放BorderLayout.CENTER,panel1会放BorderLayout.PAGE_START。此外,应设置网格的首选大小,您应该在 JFrame after 添加所有组件但 before 上调用 pack()可见或设置其位置。

其他小问题:

  • None 个当前字段应为 public 或静态。
  • 您应该在非静态代码中而不是在 main 方法中向 JFrame 添加组件。
  • 如果您需要向外部静态世界公开任何属性,请提供您的 class public getter 方法,这将允许您仅公开必要的内容并在受控的范围内方式。

测试代码如下。请注意,我没有可用的女王图片,因此我创建了一个您不需要的方法,private Icon createQueenIcon()。这样你的代码将 运行 在我的系统上。此外,为了制作代码 运行 并进行编译,我创建并包含了必要的框 class。将来,请确保您包含我们能够编译和 运行 您的代码所需的所有内容!

import javax.swing.*;
import javax.swing.border.LineBorder;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.*;

public class ChessBoardGUI extends JFrame {
    private static final long serialVersionUID = 1L;

    // !! code changes below only to allow me to run your code without
    // your images. !!
    // ImageIcon queenP = new ImageIcon(getClass().getResource("/images/queen.png"));
    // Image img = queenP.getImage();
    // Image newImg = img.getScaledInstance(40, 40,
    // java.awt.Image.SCALE_SMOOTH);
    private ImageIcon queenPic = createQueenIcon(); //!! delete this

    // all fields should be private and non-static
    private JButton tip;
    private JButton safe;
    private JLabel ifNotSafe;
    private JButton[][] chessBoxes = new JButton[8][8];
    private JPanel chessBoard;
    private ArrayList<Boxes> queensOnBoard = new ArrayList<Boxes>();

    public ChessBoardGUI() {
        createBoard();

        add(chessBoard, BorderLayout.CENTER); // Do this here

        // !! createOtherThings(); // get rid of -- put in constructor
        safe = new JButton("Safe?");
        tip = new JButton("Tip");
        ifNotSafe = new JLabel("Status of Board is displayed here...");

        ButtonListen1 safeListener = new ButtonListen1();
        ButtonListen2 tipListener = new ButtonListen2();

        safe.addActionListener(safeListener);
        tip.addActionListener(tipListener);

        // !! add the panel1 here!
        JPanel panel1 = new JPanel();
        panel1.add(ifNotSafe);
        panel1.add(safe);
        panel1.add(tip);
        add(panel1, BorderLayout.PAGE_START); // using BorderLayout constants

        // !! setSize(500, 500);

    }

    // !! so I can use images without having an image
    // !! you won't need this
    private Icon createQueenIcon() {
        int w = 40;
        BufferedImage img2 = new BufferedImage(w, w, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img2.createGraphics();
        g2.setColor(new Color(183, 65, 14));
        g2.fillRect(0, 0, w, w);
        g2.setColor(new Color(255, 215, 0));
        Font font = new Font(Font.SANS_SERIF, Font.BOLD, 30);
        g2.setFont(font);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        FontMetrics fontMetrics = g2.getFontMetrics();
        int textX = (w - fontMetrics.charWidth('Q')) / 2;
        int textY = (w - fontMetrics.getHeight()) / 2 + fontMetrics.getAscent();
        g2.drawString("Q", textX, textY);
        g2.dispose();
        return new ImageIcon(img2);
    }

    class ButtonListen1 implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (checkSolution(queensOnBoard) == true) {
                // ****THIS IS WHERE THE PROBLEM IS ******* !!
                ifNotSafe.setText("This Solution is correct so far");
                System.out.println("Solution is correct");

            } else {
                ifNotSafe.setText("This Solution is incorrect so far");
                // *********Also highlight the queens that are not safe******
                System.out.println("Solution is incorrect");
            }
        }

    }

    /*
     * ActionListener for the tip button
     */
    class ButtonListen2 implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
        }
    }

    /*
     * Creates the overall ChessBoard
     */
    public void createBoard() {
        GridLayout gridLayout = new GridLayout();
        gridLayout.setRows(8);
        gridLayout.setColumns(8);
        chessBoard = new JPanel(gridLayout);
        chessBoard.setPreferredSize(new Dimension(640, 640));
        chessBoard.setBorder(new LineBorder(Color.BLACK));
        chessBoard.setVisible(true);

        for (int x = 0; x < 8; x++) {
            for (int y = 0; y < 8; y++) {
                chessBoxes[x][y] = new JButton();
                chessBoxes[x][y].setBorderPainted(false);
                if ((x + y) % 2 == 0) {
                    chessBoxes[x][y].setBackground(Color.BLACK);
                } else {
                    chessBoxes[x][y].setBackground(Color.WHITE);
                }
                chessBoxes[x][y].setOpaque(true);
                chessBoard.add(chessBoxes[x][y]);

                BoxListener boxListen = new BoxListener();
                chessBoxes[x][y].addActionListener(boxListen);
            }
        }
    }

    class BoxListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            JButton button = ((JButton) e.getSource());

            for (int x = 0; x < 8; x++) {
                for (int y = 0; y < 8; y++) {
                    if (chessBoxes[x][y] == button) {
                        if ((isOnBoard(queensOnBoard, x, y) == false)) {
                            if (queensOnBoard.size() < 8) {
                                button.setIcon(queenPic);
                                queensOnBoard.add(new Boxes(x, y));
                            }
                        }
                        /*
                         * If there is a Queen at that JButton
                         */
                        else {
                            removeQueen(queensOnBoard, x, y);
                            button.setIcon(null);
                        }
                    }
                }
            }
        }
    }

    /*
     * Checks if a certain Box has a Queen in it or not
     * 
     * @param a Is the ArrayList of the Boxes currently occupied by Queens
     * 
     * @param x Is the X coordinate of the Box that was clicked
     * 
     * @param y Is the Y coordinate of the Box that was clicked
     */
    public boolean isOnBoard(ArrayList<Boxes> a, int x, int y) {
        for (int i = 0; i < a.size(); i++) {
            if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
                return true;
            }
        }
        return false;
    }

    /*
     * Removes a Queen from the GUI at the specified Box (JButton)
     * 
     * @param a Is the ArrayList of the Boxes currently occupied by Queens
     * 
     * @param x Is the X coordinate of the Box that was clicked
     * 
     * @param y Is the Y coordinate of the Box that was clicked
     */
    public void removeQueen(ArrayList<Boxes> a, int x, int y) {
        /*
         * Removes the box from the overall ArrayList of Boxes Occupied by
         * queens according to the x and y location
         */
        for (int i = 0; i < a.size(); i++) {
            if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
                queensOnBoard.remove(i);
            }
        }
    }

    /*
     * Return to the user which queens need to be highlighted
     * 
     * @param queensOnBoard Is the ArrayList of Boxes that are occupied by
     * Queens currently on the ChessBoard
     */
    public void conflictingQueens(ArrayList<Boxes> queensOnBoard2) {

    }

    /*
     * Checks to see if solution is correct thusfar
     * 
     * @param queensOnBoard Is the ArrayList of Boxes that are occupied by
     * Queens currently on the ChessBoard
     */
    public boolean checkSolution(ArrayList<Boxes> queensOnBoard2) {
        int size = queensOnBoard2.size();
        if (size < 1) {
            return true;
        }
        if (size == 1) {
            return true;
        }
        for (int x = 0; x < size - 1; x++) {
            for (int y = 1; y < size; y++) {
                if (queensOnBoard2.get(x).getX() == queensOnBoard2.get(y).getX()) {
                    return false;
                } else if (queensOnBoard2.get(x).getY() == queensOnBoard2.get(y).getY()) {
                    return false;
                }
            }
        }

        return true;
    }

    /*
     * Checks to see if the queen is safe from diagonal attacks
     */

    /*
     * Highlights boxes that are conflicting with one another
     * 
     * @param highlight Is the ArrayList of Boxes that are occupied by Queens
     * currently on the ChessBoard
     */
    public void highlightBoxes(ArrayList<Boxes> highlight) {
        int size1 = highlight.size();
        int size2 = queensOnBoard.size();
        if ((size1 == 0) && size1 == 1) {
            for (int x = 0; x < 8; x++) {
                for (int y = 0; y < 8; y++) {
                    chessBoxes[x][y] = new JButton();
                    chessBoxes[x][y].setBorderPainted(false);
                    /*
                     * Assigns a color to every other box
                     */
                    if ((x + y) % 2 == 0) {
                        chessBoxes[x][y].setBackground(Color.BLACK);
                    } else {
                        chessBoxes[x][y].setBackground(Color.WHITE);
                    }
                }
            }
        }
        for (int b = 0; b < size2; b++) {
            for (int a = 0; a < size1; a++) {
                if ((highlight.get(a).getX() == queensOnBoard.get(b).getX())
                        && (highlight.get(a).getY() == queensOnBoard.get(b).getY())) {
                    int x = queensOnBoard.get(b).getX();
                    int y = queensOnBoard.get(b).getY();
                    chessBoxes[x][y].setBackground(Color.RED);
                }
            }
        }
    }

    public static void main(String[] args) {
        // !! create the GUI in a Swing thread-safe manner
        SwingUtilities.invokeLater(() -> createGui());
    }

    public static void createGui() {
        JFrame frame = new ChessBoardGUI();
        // !! frame.add(chessBoard); // not here
        // !! chessBoard.setLocation(50, 50);

        // !! this does not belong within main
        // !! JPanel panel1 = new JPanel();
        // panel1.add(ifNotSafe);
        // panel1.add(safe);
        // panel1.add(tip);
        // frame.add(panel1);

        frame.setTitle("ChessBoard");
        frame.pack(); // !! call this to have your GUI size itself
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private static class Boxes {

        private int x;
        private int y;

        public Boxes(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getY() {
            return x;
        }

        public int getX() {
            return y;
        }

    }
}