realnickspiess
realnickspiess

Reputation: 47

Using java swing to call methods from another class to draw on current class

I am currently working on a Hangman game. The game uses a driver and takes in a text file of words, picks a random word and sends it to my ImageBuilder class which creates a gui with text boxes and buttons to submit letters and play the game.

If the user inputs the wrong letter, it makes a method call to my DrawArea class which changes the boolean value to true, which should trigger the drawing to show up on the panel.

I had issues figuring out how to do it and my professor said to create an instance, set the size and add it to the panel in my main gui creator method in my ImageBuilder class. Using her idea, I am getting a null pointer exception because I'm guessing it can't find the instance.

I tried creating the instance in the method that calls the drawings, and that didn't display anything either. My drawings aren't complete, but I'm just trying to get things to display at this point.

Any help on this would be greatly appreciated.

Here is my code:

Game.java:

import java.util.*;
import java.io.*;


public class Game {
    /** The main program will perform the following steps
    * 1. Take in a text file
    * 2. Read through the text file and select a random word
    * 3. Create an instance of ImageBuilder and pass the random word through
    */


    public static void main(String[] args) throws FileNotFoundException {
        ImageBuilder n = new ImageBuilder(grabWord(args[0]));

    }
    /**
     * Opens a file and parses the formatted file
     *  reads on each line of the file and splits the string into an array
     *  grabs the ages of the entries and sums them to print to screen
     * @param fileName the path to input file
     *
     */
    private static String grabWord(String fileName)throws FileNotFoundException {
        int sum = 0;
        ArrayList<String> words = new ArrayList<>();
        Scanner fileScan = new Scanner(new File(fileName));
        while(fileScan.hasNextLine()){
            sum++;
            String line = fileScan.nextLine();
            words.add(line);
        }
        Random rand = new Random();
        int randNum = rand.nextInt(sum);
        System.out.println(randNum);
        String test = words.get(randNum-1);
        System.out.println(test);
        return (test);
    }
}

ImageBuilder.java

import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;

public class ImageBuilder extends JPanel {

    // Set Frame Size Variables
    private static final int FRAME_WIDTH = 700;
    private static final int FRAME_HEIGHT = 800;
    //Create frame
    private JFrame frame;
    private int FIELD_WIDTH = 10;
    // Create Panels
    private JPanel panel1;
    private JPanel panel2;
    final JTextField b = new JTextField(FIELD_WIDTH);
    // Create Labels
    private JLabel underscores;
    private JLabel wordLabel;
    private JLabel wordToGuessLabel;
    private JLabel textLabel;
    private JLabel guessText;
    private JLabel guessedLettersArea;
    // Variable for number of letters in word
    private int numOfLetters;
    // Text field
    private JTextField wordInput;
    // Text are for the word
    private JTextArea wordResults;
    // Create button
    private JButton button;
    // String for word
    private String word;
    // Array list for __'s and word
    private ArrayList<String> wordDisplay;
    // String for guessed letters
    private String guessedLetters;
    // DrawArea
    private DrawArea draw;
    private int incorrectGuesses;

    public ImageBuilder(String word){
        DrawArea draw = new DrawArea();
        // Pass the word through
        this.word = word;

        // Initialize word display array to display __ array
        wordArrayCreator();

        // Create Guess Text
        //JLabel label3 = new JLabel("Guess a letter:");
        //Dimension size2 = label3.getPreferredSize();
        // Set location and size of label2
        //label3.setBounds(140, 70, size2.width, size2.height);

        // Call Methods
        createAndShowGui();
        createButton();
        createTextField();
        //createPanel();
        createGuessArea();


        //button.setLayout(null);
        panel1.add(textLabel);
        panel1.add(wordInput);
        panel1.add(button);
        panel1.add(guessText);
        panel1.add(guessedLettersArea);

        // Create Word box
        JPanel letterPanel = new JPanel();

        // Set frame as visible
        frame.setVisible(true);

        // Add panel1 to frame
        frame.add(panel1);




    }

    /**
     * Creates wordDisplay Array to display word
     *
     */
    private void wordArrayCreator() {
        // Create array list for word, replace each word with string: "__ "
        wordDisplay = new ArrayList<>();
        for (int i = 0; i <= word.length() - 1; i++) {
            String add = "__ ";
            wordDisplay.add(add);
        }
    }

    /**
     * Creates base layer of gui w/o any
     * interactive changes
     */
    private void createAndShowGui() {
        // Initialize Frame and Panels
        frame = new JFrame("Hangman");
        panel1 = new JPanel();
        //panel2 = new JPanel();

        // Allows manual layout for both panels
        panel1.setLayout(null);
        //panel2.setLayout(null);

        // Create label with text
        wordLabel = new JLabel("Word to Guess: ");
        Dimension size = wordLabel.getPreferredSize();

        // Set location and size of label
        wordLabel.setBounds(130, 22, size.width, size.height);

        // Add label to panel
        panel1.add(wordLabel);
        panel1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // Initializes frame content
        frame.getContentPane();

        // Create label for array, replacing "[", "]" and "," with ""
        underscores = new JLabel(wordDisplay.toString().replace("[","")
                .replace("]","").replace(",",""));
        //Dimension size3 = underscores.getPreferredSize();
        // Place underscore text label
        underscores.setBorder(BorderFactory.createLineBorder(Color.gray));
        underscores.setBounds(230, 20, 250, 22);
        // Add label of underscores to panel1
        panel1.add(underscores);

        // Create label for number of letters text
        numOfLetters = word.length();
        // Create label for the amount of letters to guess
        wordToGuessLabel = new JLabel("The word to guess has " + numOfLetters + " letters");
        Dimension size1 = wordToGuessLabel.getPreferredSize();
        // Set location and size of wordToGuessLabel
        wordToGuessLabel.setBounds(230, 45, size1.width, size1.height);

        // Initializing draw area and setting size
        DrawArea draw = new DrawArea();
        draw.setLayout(null);
        draw.setPreferredSize(new Dimension(500, 500));

        // Adding draw area to panel
        panel1.add(draw);

        // Add label to panel
        panel1.add(wordToGuessLabel);

        // Set up settings for frame
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);

    }

    /**
     * Creates label and text box to input
     * through action listener
     */
    private void createTextField() {
        textLabel = new JLabel("Guess a Letter: ");
        Dimension size4 = textLabel.getPreferredSize();
        // Set location and size of label
        textLabel.setBounds(160, 70, size4.width, size4.height);
        // Create word input area
        wordInput = new JTextField(6);
        // Set word input Size and set default text as ""
        Dimension size5 = wordInput.getPreferredSize();
        wordInput.setBounds(260, 70, size5.width, size5.height);
        wordInput.setText("");
        wordInput.isEditable();
        wordInput.isEnabled();
    }

    /**
     * Creates labels for guessed text and box for
     * displaying letters that have been guessed
     */
    private void createGuessArea() {
        // String for letters that have been guess
        guessedLetters = "";
        guessText = new JLabel("Guessed Letters: ");
        //Dimension size6 = guessText.getPreferredSize();
        guessText.setLayout(null);
        // Set location and size of label
        guessText.setBounds(165, 100, 150, 30);
        guessedLettersArea = new JLabel(guessedLetters.replace("[","")
                .replace("]","").replace(",",""));
        // Set location and size of label
        guessedLettersArea.setBounds(275, 105, 150, 22);
        guessedLettersArea.setBorder(BorderFactory.createLineBorder(Color.gray));
    }

    /**
     * Creates button to submit guessed letter
     */
    private void createButton() {
        // Initialize button
        button = new JButton("Submit Letter");
        button.setLayout(null);
        button.setBounds(335, 68, 120, 25);
        ActionListener listener = new AddLetterListener();
        button.addActionListener(listener);
        // Add button to panel1
        panel1.add(button);
    }

    /**
     * Action listener for button and text box
     * to submit letter.  Does logic for if letter has been guessed
     * and calls methods to add letters to correct arrays
     */
    class AddLetterListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            // Grab text input
            String input = (wordInput.getText());
            input = input.toLowerCase();
            // Checks for at least one letter
            if (input.length() < 1) {
                JOptionPane.showMessageDialog(frame, "You need to guess one letter.");
                wordInput.setText("");
                return;
            }
            // Checks for more than one letter
            if (input.length() > 1) {
                JOptionPane.showMessageDialog(frame, "You can only guess one letter.");
                wordInput.setText("");
                return;
            }
            if (guessedLetters.contains(input)) {
                JOptionPane.showMessageDialog(frame, "You have already guessed that letter, try again.");
                wordInput.setText("");
                return;
            }
            if (incorrectGuesses == 7) {
                wordInput.setEnabled(false);
            }
            else {
                // Checks if word contains input letter
                if (word.contains(input)) {
                    wordInput.setText("");
                    int i = word.indexOf(input);
                    // Locates first index
                    while(i >= 0) {
                        System.out.println(i);
                        updateArray(i, input);
                        updateGuesses(input);
                        i = word.indexOf(input, i+1);
                    }
                }
                else {
                    updateGuesses(input);
                    drawingCall();
                    wordInput.setText("");
                    return;
                }
            }
        }
    }

    /**
     * Updates the string that contains the guessed letter
     * @param letter : the letter that has been guessed
     */
    private void updateGuesses(String letter) {
        if (!(guessedLetters.contains(letter))) {
            guessedLetters = guessedLetters + " " + letter;
            guessedLettersArea.setText(guessedLetters);
        }
    }

    /**
     * Calls instance of draw and should call method within DrawArea class
     */
    private void drawingCall() {
        incorrectGuesses++;
        System.out.println(incorrectGuesses);
        if(incorrectGuesses == 1) {
            draw.drawGallows();
            System.out.println("Suppose Gallows");
            repaint();
        }
        if(incorrectGuesses == 2) {
            draw.drawHead();
            System.out.println("Suppose head");
            repaint();
        }
        if(incorrectGuesses == 3) {
            draw.drawBody();
            System.out.println("Suppose body");
            repaint();
        }
        if(incorrectGuesses == 4) {
            draw.drawLeftArm();
            System.out.println("Suppose left arm");
            repaint();
        }
        if(incorrectGuesses == 5) {
            //drawArea.drawRightArm();
            System.out.println("Suppose right arm");
            repaint();
        }
        if(incorrectGuesses == 6) {
            draw.drawLeftLeg();
            System.out.println("Suppose left leg");
            repaint();
        }
        if(incorrectGuesses == 7) {
            draw.drawRightLeg();
            System.out.println("Suppose right leg");
            repaint();
        }
    }

    /**
     * Updates correctly guessed letters in the word array
     */
    private void updateArray(int placeOfIndex, String letter) {
        wordDisplay.set(placeOfIndex, letter);
        underscores.setText(wordDisplay.toString().replace("[","")
                .replace("]","").replace(",",""));
    }



}

DrawArea.java

import java.awt.*;
import javax.swing.*;

public class DrawArea extends JComponent {
    private boolean gallows;
    private boolean head;
    private boolean body;
    private boolean leftArm;
    private boolean rightArm;
    private boolean leftLeg;
    private boolean rightLeg;


    public DrawArea() {

    }

    public void drawGallows() {
        gallows = true;
        System.out.println("Drawing Gallows");
    }

    public void drawHead() {
        head = true;
        System.out.println("Drawing Head");
        repaint();
    }

    public void drawBody() {
        body = true;
        System.out.println("Drawing body");
        repaint();
    }

    public void drawLeftArm() {
        leftArm = true;
        System.out.println("Drawing left arm");
        repaint();
    }

    public void drawRightArm() {
        rightArm = true;
        System.out.println("Drawing right arm");
        repaint();
    }

    public void drawLeftLeg() {
        leftLeg = true;
        System.out.println("Drawing left leg");
        repaint();
    }

    public void drawRightLeg() {
        rightLeg = true;
        System.out.println("Drawing right leg");
        repaint();
    }

    public void paintComponent(Graphics g) {
        if(gallows){
            g.fillRect(400, 400, 100, 100);// Base
            //g.fillRect(300, 700, 50, 400);// Pole
            //g.fillRect(100, 200, 400, 10);// Top
            //g.fillRect(100, 220, 50, 20);// Little Drop
            repaint();
        }
        if(head){
            g.drawOval(120, 200, 50, 50);
        }
        if(body) {
            g.fillRect(125, 240, 50, 100);
        }
        if(leftArm) {

        }
        if(rightArm) {

        }
        if(leftLeg) {

        }
        if(rightLeg) {

        }

    }

}

Upvotes: 0

Views: 1468

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347244

You're shadowing your variables:

public class ImageBuilder extends JPanel {
    //...
    private DrawArea draw;

    public ImageBuilder(String word){
        DrawArea draw = new DrawArea();

You've defined draw as an instance field of ImageBuilder, but in the constructor, you've re-defined draw as a local variable, which is only accessible from within the context of the constructor. This means your instance field is null

Remove the local declaration, for example:

public class ImageBuilder extends JPanel {
    //...
    private DrawArea draw;

    public ImageBuilder(String word){
        draw = new DrawArea();

Your use of null layouts is going to cause you no end of issues. I'd highly recommend you make the time to better understand the layout API and make use of it. See Laying Out Components Within a Container for more details

now the drawings won't display. Any input on that?

As I said, null layouts will come back to haunt you...

private void createAndShowGui() {
    //...

    // 🤨
    // Allows manual layout for both panels
    panel1.setLayout(null);
    //panel2.setLayout(null);

    // Another instances??
    // Initializing draw area and setting size
    DrawArea draw = new DrawArea();
    // Pointless
    draw.setLayout(null);
    // Pointless
    draw.setPreferredSize(new Dimension(500, 500));

    // Adding draw area to panel
    panel1.add(draw);
    //...
}

panel1 has no layout manager, so using setPreferredSize is pointless, as it relates to the layout management system ... although I'd generally discourage it's use and recommend overriding the classes getPreferredSize instead.

So. When you do panel1.add(draw), draw has no size or location information associated with it, meaning, Swing won't even bother wasting its time painting it.

Upvotes: 1

Related Questions