Использование Java Swing для вызова методов из другого класса для рисования на текущем классе - PullRequest
0 голосов
/ 10 октября 2019

Я сейчас работаю над игрой Hangman. Игра использует драйвер и принимает текстовый файл слов, выбирает случайное слово и отправляет его в мой класс ImageBuilder, который создает графический интерфейс с текстовыми полями и кнопками для отправки писем и игры.

Еслипользователь вводит неправильную букву, он вызывает метод для моего класса DrawArea, который изменяет логическое значение на true, что должно приводить к отображению чертежа на панели.

У меня были проблемы с выяснением, как это сделатьи мой профессор сказал создать экземпляр, установить размер и добавить его на панель в моем основном методе создания графического интерфейса в моем классе ImageBuilder. Используя ее идею, я получаю исключение нулевого указателя, потому что я предполагаю, что он не может найти экземпляр.

Я попытался создать экземпляр в методе, который вызывает чертежи, и он ничего не отображалили. Мои рисунки не завершены, но я просто пытаюсь заставить вещи отображаться на этом этапе.

Любая помощь по этому вопросу будет принята с благодарностью.

Вот мой код:

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

        }

    }

}

1 Ответ

1 голос
/ 10 октября 2019

Вы скрываете свои переменные:

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

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

Вы определили draw как поле экземпляра ImageBuilder, но в конструкторе вы повторно определили draw каклокальная переменная, которая доступна только из контекста конструктора. Это означает, что ваше поле экземпляра имеет значение null

Удалите локальную декларацию, например:

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

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

Использование макетов null не вызовет никаких проблем. Я настоятельно рекомендую вам уделить время, чтобы лучше понять API макета и использовать его. См. Расположение компонентов в контейнере для получения более подробной информации

, теперь чертежи не будут отображаться. Есть какие-нибудь входные данные?

Как я уже сказал, null макеты вернутся, чтобы преследовать вас ...

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 не имеет менеджера компоновки, поэтому использованиеsetPreferredSize бессмысленно, так как это относится к системе управления компоновкой ... хотя я бы вообще не рекомендовал ее использовать и рекомендовал бы вместо нее использовать классы getPreferredSize.

Итак. Когда вы делаете panel1.add(draw), draw не имеет никакой связанной с ним информации о размере или местоположении, то есть Swing даже не потратит зря свое время на рисование.

...