javaswingfontsgraphics2dfontmetrics

Horizontally Centering Text in a Window with Java


I'm trying to figure out how to center text horizontally in a window using Graphics2D and FontMetrics. I made a method that I hoped would measure the length of the string once it was changed to a Font type, but it's not centering the text very well.

How can I center the text properly?

Title is not well centered: enter image description here

My MainClass class:

import java.io.File;
import java.io.IOException;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainClass extends JPanel{

   static final int WINDOW_WIDTH = 1600;
   static final int WINDOW_HEIGHT = 900;

   // Displays the game window.
   private static void displayGameWindow() {
      Color tan = new Color(155, 136, 120);

      JFrame frame = new JFrame("Bandit King");
      frame.setBackground(tan);
      frame.getContentPane().add(new MainClass());
      frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
      frame.setVisible(true);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

   }


   // Imports a font.
   private static void registerFont() {
      try {
         GraphicsEnvironment ge = 
               GraphicsEnvironment.getLocalGraphicsEnvironment();
         Font f = Font.createFont(Font.TRUETYPE_FONT, new File("OLDSH.TTF"));
         ge.registerFont(f);

      } catch (IOException|FontFormatException e) {
         e.printStackTrace();
         System.out.println("ERROR loading font, switching to serif.");
         Font f = new Font("Serif", Font.PLAIN, 12);
      }
   }


   // Calls functions to display the screen
   @Override
   public void paint(Graphics g) {
      Dimension d = this.getPreferredSize();
      Graphics2D g2d = (Graphics2D) g;
      g.fillRect(0,  0,  d.width, d.height);

      // default font settings
      String fontName = "OldStyle 1 HPLHS";
      String fontType = "BOLD";
      int[] color = {0, 0, 0};
      int fontSize = 25;

      // display game title
      String[] title = {"Bandit King"};
      int titlePos = DisplayText.findHorizontalCenter(g2d, title[0], d.width);
      DisplayText.displayText(g2d, 
            title, fontName, "BOLD", 
            color, 
            titlePos, 70, 60, 1);
      g2d.drawRect(0, 0, d.width - 1, d.height - 1);

      // display menu
      String[] menuArr = {
            "(a) Start a new game", 
            "(b) Load a saved game",
            "(c) Exit the game",
            "(d) Resume the game"};

      DisplayText.displayText(g2d,
            menuArr, fontName, fontType, color, 40, 210, fontSize, 2);
   }


   public static void main(String[] args) {
      registerFont();
      displayGameWindow();
   }
}

My DisplayText class:

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;

public class DisplayText {
   /** 
    * Displays text to window
    * 
    * PARAMETERS:
    * g2d            A Graphics2D object
    * text           The text to be drawn to screen
    * fontName       The name of the font to be used.
    * fontType       Whether the font is bold, italic, or neither.
    * color          Array of length 3, to represent RGB color
    * xPos           The x-position of the text.    
    * yPos           The y-position of the text.
    * fontSize       The size of the font.
    * menuSpacing    How far apart menu text should be. (Never zero!)
    */
   public static void displayText(Graphics2D g2d,
         String[] textItems, String fontName, String fontType, 
         int[] color,
         int xPos, int yPos, int fontSize, double menuSpacing) {

      // Check for problems
      // if textItems is empty
      if (textItems.length < 1) {
         System.out.println("DisplayText.displayText() ERROR" +
               System.lineSeparator() +
               "no items in String[] textItems");
         return;
      // if color array isn't length 3.
      } else if (color.length != 3) {
         System.out.println("DisplayText.displayText() ERROR" +
               System.lineSeparator() +
               "color.length != 3");
         return;
      // if menuSpacing isn't a positive number or > 0.
      } else if (menuSpacing <= 0) {
         System.out.println("DisplayText.displayText() ERROR" +
               System.lineSeparator() +
               "menuSpacing <= 0");
      }

      // assign appropriate int according to fontType
      fontType = fontType.toLowerCase();
      int fontNum;
      switch(fontType) {
         case "bold" :
            fontNum = Font.BOLD;
            break;
         case "italic" :
            fontNum = Font.ITALIC;
            break;
         case "plain" :
            fontNum = Font.PLAIN;
            break;
         default :
            fontNum = Font.PLAIN;
            break;
      }

      g2d.setFont(new Font(fontName, fontNum, fontSize));
      g2d.setColor(new Color(color[0], color[1], color[2]));

      // Determine whether to print several lines or one.
      if (textItems.length == 1) {
         g2d.drawString(textItems[0], xPos, yPos);
      } else { 
         // Draw several lines 
         for (int i = 0; i < textItems.length; i++) {
            g2d.drawString(textItems[i], xPos, yPos);
            // Spaces menu items by the height of the font and menuSpacing
            yPos += (int) (g2d.getFontMetrics().getAscent() * menuSpacing);
         }
      }
   }

   // Finds the x-position centered text should be at.
   public static int findHorizontalCenter(Graphics2D g2d,
         String s, int w) {
     Font f = g2d.getFont();
     FontMetrics fm = g2d.getFontMetrics(f);
     int width = fm.stringWidth(s);
     System.out.println(width);
     int x = (MainClass.WINDOW_WIDTH  - width)/2;
     return x;
   }


}

Solution

  • Try setting the font size before getting the text's width.