Creating a Screen

Published — Edited

Initializing VTerminal

Before creating a screen, you must first initialize VTerminal. This must be done before running any Swing-related code, or else your program will be running in an undefined state which may cause graphical issues.

There are two basic ways to run the initialization code. The only difference being that the second way allows you to specify the font size. The font size is applied to all components and cannot be changed after it has been set.


public class ExampleA {
	public static void main(final String[] args) {
		try {
			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance());
		} catch (final UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
	}
}


public class ExampleB {
	public static void main(final String[] args) {
		try {
			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance(24));
		} catch (final UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
	}
}

The following is a more advanced way, which allows you to initialize VTerminal with a custom font and font size. Please do not attempt to run this example as it references a non-existant file.


public class ExampleI {
	public static void main(final String[] args) {
		try {
			final var file = new File("Font.ttf");
			final var fis = new FileInputStream(file);

			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance(fis, 24));

			fis.close();
		} catch (final UnsupportedLookAndFeelException | IOException | FontFormatException e) {
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(() -> {
			final var panel = new VPanel(40, 20);

			final var frame = new JFrame();
			frame.add(panel);
			frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

			frame.setVisible(true);
			frame.pack();
			frame.setLocationRelativeTo(null);

			panel.setCodePointAt(0, 0, 'A');
		});
	}
}

Java supports TrueType, OpenType, and PostScript Type 1 fonts.

Screen Creation

When it comes to screen creation, there are a few methods to choose from. Each of the following methods achieves the same result.

If you're not familiar with SwingUtilities.invokeLater, it ensures that the code is run on the Event Dispatch Thread (EDT). This is an important concept to know when working with Swing, so please take the time to learn about the EDT and how to use it.


public class ExampleC {
	public static void main(final String[] args) {
		try {
			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance());
		} catch (final UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(() -> {
			final var frame = new VFrame(40, 20);
			frame.setVisible(true);
			frame.pack();
			frame.setLocationRelativeTo(null);
		});
	}
}


public class ExampleD {
	public static void main(final String[] args) {
		try {
			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance());
		} catch (final UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(() -> {
			final var frame = new VFrame(new VPanel(40, 20));
			frame.setVisible(true);
			frame.pack();
			frame.setLocationRelativeTo(null);
		});
	}
}


public class ExampleE {
	public static void main(final String[] args) {
		try {
			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance());
		} catch (final UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(() -> {
			final var frame = new JFrame();
			frame.setContentPane(new VPanel(40, 20));
			frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

			frame.setVisible(true);
			frame.pack();
			frame.setLocationRelativeTo(null);
		});
	}
}


public class ExampleF {
	public static void main(final String[] args) {
		try {
			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance());
		} catch (final UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(() -> {
			final var frame = new JFrame();
			frame.add(new VPanel(40, 20));
			frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

			frame.setVisible(true);
			frame.pack();
			frame.setLocationRelativeTo(null);
		});
	}
}

Though each of the above methods achieves the same result, there is one key difference. When you want to update the screen in Examples C & D, you have to use the frame.getContentPane() method to retrieve the panel. When you want to update the screen in Examples E & F, you already have a reference to the panel.


public class ExampleG {
	public static void main(final String[] args) {
		try {
			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance());
		} catch (final UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(() -> {
			final var frame = new VFrame(40, 20);
			frame.setVisible(true);
			frame.pack();
			frame.setLocationRelativeTo(null);

			final var panel = frame.getContentPane();
			panel.setCodePointAt(0, 0, 'A');
		});
	}
}


public class ExampleH {
	public static void main(final String[] args) {
		try {
			UIManager.setLookAndFeel(VTerminalLookAndFeel.getInstance());
		} catch (final UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(() -> {
			final var panel = new VPanel(40, 20);

			final var frame = new JFrame();
			frame.add(panel);
			frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

			frame.setVisible(true);
			frame.pack();
			frame.setLocationRelativeTo(null);

			panel.setCodePointAt(0, 0, 'A');
		});
	}
}

Further Reading