简体   繁体   中英

How do you make a JTextField's number bigger than another JTextField's number?

I'm trying to get a JTextField's number greater than another JTextField's number for my Tic Tac Toe project, but I keep getting exceptions.. For instance, if gridSizeField 's number is 6, than playersField 's number would not be 5. I want it to be 6 or greater.

This is my all my code so far:

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.Graphics;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

/**
 * A class that shows the xy coordinates near the mouse cursor.
 */
class AlsXYMouseLabelComponent extends JComponent {
    
    public int x;
    public int y;

    /**
     * Uses the xy coordinates to update the mouse cursor label.
     */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        String coordinates = x + ", " + y; // Get the cordinates of the mouse
        g.setColor(Color.red);
        g.drawString(coordinates, x, y); // Display the coordinates of the mouse
    }
    
}

/**
 * The class that has tools that can be used for <code>JTextField</code>s.
 */
class JTextFieldTool {
    
    /**
     * Make a JTextField only accept numbers
     * @param textField1 The JTextField that will only accept numbers
     * @param textField2 The JTextField that the will always be greater than the first JTextField
     * @param limit The amount of digits that the JTextField can have
     */
    public static void setAcceptNumberOnly(JTextField textField1, int limit) {
         
        textField1.setDocument(new JTextFieldTool.JTextDocLimit(limit));
        textField1.select(textField1.getText().length(), 0);
        textField1.addKeyListener(new KeyAdapter() {
            
            private JTextField obj = textField1;
 
            @Override
            public void keyTyped(KeyEvent event) {
                
                char c = event.getKeyChar();
                
                /**
                 * If the character that the user tries to type in a character that is not a digit, don't put the character in the JTextField
                 */
                if (!Character.isDigit(c) || c == KeyEvent.VK_BACK_SPACE || c == KeyEvent.VK_DELETE)
                    event.consume();
                
            }
 
            @Override
            public void keyReleased(KeyEvent event) {
                
                char c = event.getKeyChar();
                
                if (Character.isDigit(c) || c == KeyEvent.VK_BACK_SPACE || c == KeyEvent.VK_DELETE || c == KeyEvent.VK_LEFT || c == KeyEvent.VK_RIGHT) {
                    
                    String textStr = this.obj.getText().replace(",", "");
 
                    if (textStr.isEmpty())
                        textStr = "0";
 
                    int selectionStart = this.obj.getSelectionStart();
                    int lengthToEnd = this.obj.getText().length() - selectionStart; 
                    int newSelectionStart = this.obj.getText().length() - lengthToEnd;
                    this.obj.select(newSelectionStart, 0);
 
                }
                
            }
            
        });
        
    }
    
    /**
     * Makes a JTextField accept numbers that are less than another JTextField.
     * @param textField1 The first JTextField which is less than the other second one.
     * @param textField2 The second JTextField which is always greater than the first one.
     */
    public static void makeThisTextFieldLesser(JTextField textField1, JTextField textField2) {
        
        textField1.addKeyListener(new KeyAdapter() {
            
            @Override
            public void keyTyped(KeyEvent event) {
                
                char c = event.getKeyChar();
                String label = textField2.getText();
                
                /**
                 * If the user tries to enter a number in the first text field that is greater than or equal to the second text field, don't put the number in
                 */
                if (c >= textField2.getText().charAt(0) || label.isEmpty())
                    textField2.setText("3");
                    event.consume();
                
            }   
            
        });
        
    }
 
    public static class JTextDocLimit extends PlainDocument {
    
        private int limit;
    
        public JTextDocLimit(int limit) {
            this.limit = limit;
        }
    
        @Override
        public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
        
            if (str == null)
                return;
 
            if ((getLength() + str.length()) <= limit) 
                super.insertString(offset, str, attr);
            
        }
        
    }

}

class Canvas extends JComponent {
    
    /**
     * Draws the grid that the players are going to use for their Tic Tac Toe game.
     * @param g the <code>Graphics</code> object that is used to draw the lines of the grid
     */
    public static void drawGrid(Graphics g) {
        
        g.drawOval(10, 10, 10, 10); 
        
    }
    
    /**
     * Displays the grid that was drawn in the <code>drawGrid</code> method.
     */
    @Override
    public void paint(Graphics g) {         
        super.paint(g);
        drawGrid(g);
    }
    
}


public class TicTacToe implements ActionListener {
        
    /**
     * Global variables used so that they are in the scope of the actionPerformed method or other variables
     */
    private static JPanel panel;
    private static JFrame frame;
    private static JTextField gridSizeField;
    
    
    /**
     * Create a GUI that will let the user customize options for the game, and display the grid using lines in the Graphics2D class
     */
    public static void main(String[] args) {
        
        panel = new JPanel();

        frame = new JFrame();
        frame.setSize(1365, 767);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("Tic Tac Toe");
        frame.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
        frame.setVisible(true);
        frame.add(panel);
        
        panel.setLayout(null);
        
        AlsXYMouseLabelComponent alsXYMouseLabel = new AlsXYMouseLabelComponent();
        
        /**
         * Add the component to the DRAG_LAYER of the layered pane (JLayeredPane)
         */
        JLayeredPane layeredPane = frame.getRootPane().getLayeredPane();
        layeredPane.add(alsXYMouseLabel, JLayeredPane.DRAG_LAYER);
        alsXYMouseLabel.setBounds(0, 0, frame.getWidth(), frame.getHeight());

        /**
         * Add a mouse motion listener, and update the crosshair mouse cursor with the xy coordinates as the user moves the mouse
         */
        frame.addMouseMotionListener(new MouseMotionAdapter() {
            
            /**
             * Detects when the mouse moved and what the mouse's coordinates are.
             * @param event the event that happens when the mouse is moving.
             */
            @Override
            public void mouseMoved(MouseEvent event) {      
                alsXYMouseLabel.x = event.getX();
                alsXYMouseLabel.y = event.getY();
                alsXYMouseLabel.repaint();
            }
        
        });
        
        JLabel title = new JLabel("Tic Tac Toe");
        title.setBounds(500, 100, 550, 45);
        title.setFont(new Font("Verdana", Font.PLAIN, 50));
        panel.add(title);
        
        JLabel playersLabel = new JLabel("Number of Players: ");
        playersLabel.setBounds(280, 335, 285, 25);
        playersLabel.setFont(new Font("Verdana", Font.PLAIN, 20));
        panel.add(playersLabel);
        
        JTextField playersField = new JTextField();
        playersField.setBounds(480, 335, 30, 25);
        playersField.setText("1"); // Make the players field already have an integer so that the program won't throw a NumberFormatException
        playersField.setFont(new Font("Verdana", Font.PLAIN, 20));
        playersField.setHorizontalAlignment(JTextField.CENTER);
        JTextFieldTool.setAcceptNumberOnly(playersField, 1); // Make the players field accept only numbers that have one digit
        JTextFieldTool.makeThisTextFieldLesser(playersField, gridSizeField); // Make the players field less than the grid size field
        panel.add(playersField);
        
        JLabel computersLabel = new JLabel("How Many Computers Are Included?");
        computersLabel.setBounds(280, 365, 575, 25);
        computersLabel.setFont(new Font("Verdana", Font.PLAIN, 20));
        panel.add(computersLabel);
        
        JTextField computersField = new JTextField();
        computersField.setBounds(655, 365, 30, 25);
        computersField.setText("1");
        computersField.setFont(new Font("Verdana", Font.PLAIN, 20));
        computersField.setHorizontalAlignment(JTextField.CENTER);
        JTextFieldTool.setAcceptNumberOnly(computersField, 1);
        panel.add(computersField);
        
        JLabel gridSizeLabel = new JLabel("Grid Size: ");
        gridSizeLabel.setBounds(720, 335, 220, 25);
        gridSizeLabel.setFont(new Font("Verdana", Font.PLAIN, 20));
        panel.add(gridSizeLabel);
        
        JTextField gridSizeField = new JTextField();
        gridSizeField.setBounds(830, 335, 30, 25);
        gridSizeField.setText("3");
        gridSizeField.setFont(new Font("Verdana", Font.PLAIN, 20));
        gridSizeField.setHorizontalAlignment(JTextField.CENTER);
        JTextFieldTool.setAcceptNumberOnly(gridSizeField, 1); // Make the grid size field accept only numbers that have one digit
        panel.add(gridSizeField);
        
        JButton playButton = new JButton("Let's Play!");
        playButton.setBounds(530, 480, 220, 25);
        playButton.setFont(new Font("Verdana", Font.PLAIN, 20));
        playButton.addActionListener(new TicTacToe());
        panel.add(playButton);
        
    }
    
    /**
     * Removes all of the components of the panel when the Play <code>JButton</code> is clicked and replaces it with the canvas that the Tic Tac Toe grid will be drawn on.
     * @param event the event that happens when the Play button is clicked
     */
    @Override
    public void actionPerformed(ActionEvent event) {
        
        Component[] components = panel.getComponents();
        
        /**
         * Loop through all of the components in the panel and remove them
         */
        for (Component component : components)
            panel.remove(component);
        
        panel.revalidate();
        panel.repaint();
        
        frame.getContentPane().add(new Canvas()); // Add the canvas to the frame so that the lines drawn in the paint() method can be visible
        
    }
    
    /**
     * Displays the player's symbol when they click on a square in the grid.
     * @param event the event that happens when a square in the grid is clicked
     */
    public void mouseClicked(MouseEvent event) {
        
    }
    
}

If you have any suggestions, then I'd be very glad with that.

Reason for NPE is "null value for gridSizeField passed in this method call".

JTextFieldTool.makeThisTextFieldLesser(playersField, gridSizeField); 

Instead of calling the method makeThisTextFieldLesser() , adding KeyListener after instantiation of gridSizeField would avoid NPE. Just modified the code a bit.

playersField.addKeyListener(new KeyAdapter() {            
        @Override
        public void keyTyped(KeyEvent event) {                
            if (gridSizeField.getText().isEmpty() || event.getKeyChar() < gridSizeField.getText().charAt(0))
                event.consume();                
        }               
    });

Hope it would help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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