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
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…
With a layout manager…
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
.