Skip to content
Advertisement

Java – JTextArea refuses to print strings that are just whitespace [closed]

I have written a command terminal using Swing components. The snippets of code below contain everything I think could be part of the problem. What is happening is in Snippet #1, when I call printBoard(), it ignores the whitespace in the values[][] array. I tried switching to String[][] instead of char[][] but it didn’t work.

If you need more information, please ask. Thanks for your help!

EDIT: https://github.com/GlitchGamer1459/Windows-Command-Prompt-Clone

Snippet #1:

package Application.play;

import Application.control.Controller;
import Application.control.IOEngine;
import Application.control.Terminal;

public class TicTacToe {

    private static final IOEngine stringMethods = new IOEngine();

    private static char charToPrint = 'X';

    @SuppressWarnings("FieldMayBeFinal")
    private static char[][] values = {
            { ' ', ' ', ' ' },
            { ' ', ' ', ' ' },
            { ' ', ' ', ' ' }
    };

    private static void printBoard() {
        Terminal.out.println(" " + values[0][0] + " | " + values[0][1] + " | " + values[0][2] + " ");
        Terminal.out.println("---+---+---");
        Terminal.out.println(" " + values[1][0] + " | " + values[1][1] + " | " + values[1][2] + " ");
        Terminal.out.println("---+---+---");
        Terminal.out.println(" " + values[2][0] + " | " + values[2][1] + " | " + values[2][2] + " ");
    }

    private static void parseChain(String chain) { // a chain looks like this: '1.1' or this: '0.2'
        try {
            int vertical = Integer.parseInt(stringMethods.getUntilFirst('.', chain));
            int horizontal = Integer.parseInt(stringMethods.getUntilSecond('.', chain));

            if (charToPrint == 'X') {
                charToPrint = 'O';
            } else {
                charToPrint = 'X';
            }

            values[vertical][horizontal] = charToPrint;
        } catch (NumberFormatException nfe) {
            Terminal.out.println("Not A Valid Input, try again");
        } catch (ArrayIndexOutOfBoundsException e) {
            Terminal.out.println("Not A Valid Input, must be within range of 0-2");
        }
    }

    public static void runGame(String string) {
        Controller.ioEngine.clearTerminalScreen();
        parseChain(string);
        printBoard();
    }

    public static void start() {
        Terminal.setActiveCycle(2);
    }
}

Snippet #2:

package Application.control;

import javax.swing.*;

@SuppressWarnings("unused")
public class Out {
    JTextArea outputScreen;

    public Out(JTextArea outputArea) {
        outputScreen = outputArea;
    }

    public void println() {
        outputScreen.append("n");
    }

    public void println(String output) {
        outputScreen.append(output + "n");
    }

    public void println(double output) {
        outputScreen.append(output + "n");
    }

    public void println(int output) {
        outputScreen.append(output + "n");
    }

    public void println(char output) {
        outputScreen.append(output + "n");
    }

    public void println(float output) {
        outputScreen.append(output + "n");
    }
}

Snippet #3:

package Application.terminal;

import Application.control.Controller;
import Application.control.Terminal;
import Application.play.GuessGame;
import Application.play.TicTacToe;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class EventHandler implements KeyListener, ActionListener {

    @SuppressWarnings("all")
    public boolean gameAlreadyInit = false;

    //KeyListener methods
    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == 10) {
            String input = Controller.terminal.inputField.getText();
            Controller.terminal.inputField.setText("");
            switch (Terminal.getActiveCycle()) {
                case 0 -> // runs the base Terminal cycle
                    Controller.ioEngine.parseInput(input);
                case 1 -> { // runs the guessing game
                    if (!gameAlreadyInit) {
                        GuessGame.start();
                        gameAlreadyInit = true;
                    }

                    GuessGame.runGame(input);
                }
                case 2 -> {
                    if (!gameAlreadyInit) {
                        TicTacToe.start();
                        gameAlreadyInit = true;
                    }

                    TicTacToe.runGame(input);
                }
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    //ActionListener methods
    @Override
    public void actionPerformed(ActionEvent e) {

    }
}

Advertisement

Answer

So, I pulled your code, and ignoring the over use of static, null layouts and KeyListener, I changed:

outputScreen.setFont(new Font("SansSerif", Font.PLAIN, 15));

to

outputScreen.setFont(new Font("Courier", Font.PLAIN, 15));

and it now prints

enter image description here

You need to make use of a monospaced font in order to ensure that all the characters have equal widths

Also, you should follow Andrew’s advice…

outputScreen.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 15));

Now you get platform independence.

what’s wrong with the null layout?

Without a layout manager…

enter image description here

With a layout manager…

enter image description here

Resiability for free. You also don’t have to worry about the DPI or what things like accessibility might do.

null or “pixel perfect” layouts are an illusion. To many factor go into determining how a component should be sized and how components should be laid out in relationship to each other.

A lot of work has gone into solving these issues, Swing makes use of layout managers, other frameworks do similar things.

Rather then spending a lot of time tearing your hair out over why the layout breaks on some others computer, just make use of the layout managers that are already available to you – for example, BorderLayout would be a fantastic for your current layout

what’s wrong with KeyListener?

KeyListener is too low level a API for your needs. Since all you’re doing is monitoring for the Enter key anyway, you might as well make use of the ActionListener support. You’re also assuming the key code is constant.

If you want to filter the input, then you should use a DocumentFilter.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement