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.
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:
be setting the preferred size. Instead you should override the getPreferredSize()
method to return the size
set the font in the painting method. All components support a setFont() method. So just set the Font in the constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With