如何在Java中删除图形显示字符串末尾的空格?

如何在Java中删除图形显示字符串末尾的空格?,java,swing,graphics,Java,Swing,Graphics,我的类GraphicButton.java创建一个带有特定文本和字体以及矩形边框的自定义JButton。我的问题是,字符串中的最后一个字符和要删除的边框结尾之间有一些额外的空格 下面是GraphicButton的实例,其中字符串“PLAY”和字体(直接下载链接)添加到JFrame红线是我要删除的空间 以下是我正在使用的代码(JFrame创建和设置省略): GraphicButton.java: public class GraphicButton extends JButton { p

我的类
GraphicButton.java
创建一个带有特定文本和字体以及矩形边框的自定义
JButton
。我的问题是,字符串中的最后一个字符和要删除的边框结尾之间有一些额外的空格

下面是
GraphicButton
的实例,其中字符串“PLAY”和字体(直接下载链接)添加到
JFrame
红线是我要删除的空间

以下是我正在使用的代码(
JFrame
创建和设置省略):

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());
   }
}

我正在使用Java 1.8在Mac上运行Eclipse。

您可能可以使用
文本布局来获得更好的宽度计算

在下面的示例中,您可以看到使用
TextLayout
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();
            }
        });
    }
}
此外,你不应:

  • 正在设置首选大小。相反,您应该重写
    getPreferredSize()
    方法以返回大小

  • 在绘制方法中设置字体。所有组件都支持setFont()方法。所以只需在构造函数中设置字体


  • 那个空格就是字母之间的空格。我想你可以在BuffereImage上绘制“PLAY”,找到最右边的空间,删除空间,然后将修改后的BuffereImage作为图像图标传递给JButton。我喜欢你的建议@GilbertLeBlanc,只是我不知道如何执行你的建议。请在您的答案中添加一些内容,告诉我该怎么做。阅读我的文章,看看我如何操作BuffereImage。为了让您的方法正常工作,我必须在
    bounds.getX()
    bounds.getY()
    上调用
    Math.floor()
    调用
    bounds.getWidth())
    bounds.getHeight()
    因为它们大于实际的宽度和高度。我还将
    Point2D loc
    更改为
    new Point2D.float(0,getHeight())
    以将文本放在正确的位置。@TurtuWarrior,很高兴这个建议有帮助。不要忘记通过单击复选标记来“接受”答案,这样人们就知道问题已经解决。我会接受你的答案,但我注意到你没有向你的答案添加任何调用
    Math.ceil()
    Math.floor()
    。是我需要调用它们,还是这会成为未来其他用户的问题?@MasterBlaster,代码很少会100%满足您的需要,因为我们不是来为您编写代码的,只是为您指出解决问题的正确方向。无需更改此处发布的代码,因为它工作正常。也就是说,它通过绘制矩形来演示两种方法返回的不同值。如果某些值为负值,该代码如何正确绘制矩形?我不知道为什么你的价值观是负面的,这是有道理的。谢谢你的帮助。