Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove the space from the end of a string displayed with Graphics in Java?

My class GraphicButton.java creates a custom JButton with a certain text and font and a rectangular border. My problem is that there is some extra space between the last character in the string and the end of the border that I would like to remove.

Here is what an instance of a GraphicButton looks like with the string "PLAY" and the font FFF Forward (Direct Download Link) added to a JFrame. The red line is the space I would like to remove.

Here is the code I'm using (JFrame creation and setup omitted):

GraphicButton.java:

public class GraphicButton extends JButton {

   private static final long serialVersionUID = 1L;

   //Fields
   private String text;
   private Font font;

   //Constructor
   public GraphicButton(String text, Font font) {
       super(text);

       this.text = text;
       this.font = font;
       //Setting preferred size here.
       this.setPreferredSize(new Dimension(this.getFontMetrics(font).stringWidth(text), this.getFontMetrics(font).getAscent()));
   }

   @Override
   public void paintComponent(Graphics g) {
       g.setFont(this.font);

       //Draw text
       g.drawString(this.text, 0, this.getHeight());
       //Draw border
       g.drawRect(0, 0, this.getWidth(), this.getHeight());
   }
}

I'm running Eclipse on a Mac with Java 1.8.

like image 701
MasterBlaster Avatar asked Oct 19 '22 11:10

MasterBlaster


1 Answers

You might be able to use the TextLayout to get a better width calculation.

In the example below you can see the different between using the TextLayout and FontMetrics:

import javax.swing.*;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;

public class DrawTest extends JPanel
{
    String text;

    public DrawTest(String text)
    {
        this.text = text;
//      setFont( new Font("Arial", Font.PLAIN, 24) );
        setFont( new Font("Monospaced", Font.PLAIN, 24) );
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        g2d.setFont( getFont() );
        g2d.setPaint(Color.RED);

        //  Draw text using FontMetrics

        FontMetrics fm = g2d.getFontMetrics();
        Rectangle2D rect = fm.getStringBounds(text, g2d);
        rect.setRect(rect.getX() + 100, rect.getY() + 50, rect.getWidth(), rect.getHeight());
        g2d.draw(rect);

        //  Draw text using TextLayout

        g2d.setPaint(Color.BLACK);

        Point2D loc = new Point2D.Float(100, 50);
        FontRenderContext frc = g2d.getFontRenderContext();
        TextLayout layout = new TextLayout(text, getFont(), frc);
        layout.draw(g2d, (float)loc.getX(), (float)loc.getY());

        Rectangle2D bounds = layout.getBounds();
        bounds.setRect(bounds.getX()+loc.getX(), bounds.getY()+loc.getY(), bounds.getWidth(), bounds.getHeight());
        g2d.draw(bounds);
    }

    private static void createAndShowUI()
    {
        DrawTest text = new DrawTest("This is some ugly test i");

        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( text );
        frame.setSize(400, 200);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

Also you should NOT:

  1. be setting the preferred size. Instead you should override the getPreferredSize() method to return the size

  2. set the font in the painting method. All components support a setFont() method. So just set the Font in the constructor.

like image 186
camickr Avatar answered Oct 21 '22 04:10

camickr