Swing中的图标字体:在JLabel中出现的字体图标未显示

3

我正在用Java制作Swing应用程序,当然,包括按钮。我决定使用带有图标字体的JLabel来创建它们,以便具有良好的可伸缩性。我尝试了在标签中使用Font Awesome,它能够很好地工作:

Font font = Font.createFont(Font.TRUETYPE_FONT, int.class.getResourceAsStream("/fonts/fontawesome.ttf")).deriveFont(20f);
JFrame frame = new JFrame();
frame.setLayout(new FlowLayout(FlowLayout.TRAILING, 20, 20));
JLabel label1 = new JLabel("\uF144");
label1.setFont(font);
frame.add(label1);
JLabel label2 = new JLabel("\uF1B0");
label2.setFont(font);
frame.add(label2);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);

已呈现的图标:圆圈中的三角形和爪印

所以,我去了图标字体生成器(Fontello)并选择了想要的图标。我将生成的字体添加到我的应用程序中,更改了代码并进行了测试运行……但是我没有看到它们:它们就是没有出现!

我编写了测试代码(我用红色边框制作了图标,以查看会发生什么):

final Font[] font = {Font.createFont(Font.TRUETYPE_FONT, int.class.getResourceAsStream("/fonts/fontello.ttf"))};
JFrame frame = new JFrame();
frame.setLayout(new FlowLayout(FlowLayout.TRAILING, 20, 20));
JLabel size = new JLabel("Size: " + font[0].getSize2D());
frame.add(size);
// I have 12 icons in font
JLabel[] labels = new JLabel[12];
int j = 0;
// There are codes of those icons
for(char i = '\uE800'; i <= '\uE80B'; i++)
{
    JLabel label1 = new JLabel("" + i);
    label1.setFont(font[0]);
    label1.setBorder(new LineBorder(Color.RED, 1));
    label1.setForeground(Color.black);
    frame.add(label1);
    labels[j++] = label1;
}
frame.add(new JButton(new AbstractAction("-1")
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
        font[0] = font[0].deriveFont(font[0].getSize2D() - 1);
        size.setText("Size: " + font[0].getSize2D());
        for(JLabel label: labels)
        {
            label.setFont(font[0]);
        }
    }
}));
frame.add(new JButton(new AbstractAction("+1")
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
        font[0] = font[0].deriveFont(font[0].getSize2D() + 1);
        size.setText("Size: " + font[0].getSize2D());
        for(JLabel label: labels)
        {
            label.setFont(font[0]);
        }
    }
}));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);

我看到了什么?

有些启动是成功的:

test run

test run

(每次运行我都增加字体大小)

有些则不是:

test run

test run

正如你所看到的,当字体大小为8时,我无法说出发生了什么,从大小9开始-由于某种原因,字符根本没有被绘制。

怎么回事?这是swing中的一个bug还是字体存在问题?


1
你为什么要用标签而不是按钮来制作按钮? - user1803551
因为我不需要移除按钮的背景绘制(例如“-1”、“+1”按钮)。 - cybersoft
可以,但那些不是真正的按钮。无论如何,你能提供重现所需的资源文件吗? - user1803551
当然,这是“掩蔽”按钮 :) 字体在此链接中:http://s000.tinyupload.com/?file_id=05254772828174415128 - cybersoft
在我们进行调查时,我使用了GlyphVector(似乎这个正常工作),并结合JComponent来实现我的目标(它也是“掩码”按钮:)。 - cybersoft
显示剩余2条评论
1个回答

2

所以,这不是解决问题的方法,而是一种变通方法。我编写了自己的Swing组件,可以从给定的字体中绘制给定的字形:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.Rectangle2D;

public class FontIconGlyphButton extends JComponent
{
    // to avoid wrong glyph codes
    public interface FontIconGlyphCode
    {
        char toCharCode();
    }

    private final Color color;
    private final Color hoverColor;
    private final Color disabledColor;
    private final Font font;

    private GlyphVector vector;
    private Rectangle2D size;
    private FontIconGlyphCode iconCode;
    private boolean hover = false;

    public FontIconGlyphButton(Font font, FontIconGlyphCode iconCode, Color color, Color hoverColor, Color disabledColor)
    {
        this(font, iconCode, color, hoverColor, disabledColor, null);
    }

    public FontIconGlyphButton(Font font, FontIconGlyphCode iconCode, Color color, Color hoverColor, Color disabledColor, ActionListener listener)
    {
        this.font = font;
        this.color = color;
        this.hoverColor = hoverColor;
        this.disabledColor = disabledColor;
        setIconCode(iconCode);
        addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                if(listener != null)
                    listener.actionPerformed(new ActionEvent(e.getSource(), e.getID(), Action.DEFAULT));
            }

            @Override
            public void mouseEntered(MouseEvent e)
            {
                hover = true;
                repaint();
            }

            @Override
            public void mouseExited(MouseEvent e)
            {
                hover = false;
                repaint();
            }
        });
    }

    public void setIconCode(FontIconGlyphCode iconCode)
    {
        this.iconCode = iconCode;
        FontRenderContext context = new FontRenderContext(null, true, true);
        vector = font.createGlyphVector(context, String.valueOf(iconCode.toCharCode()));
        size = vector.getGlyphMetrics(0).getBounds2D();
        repaint();
    }

    public FontIconGlyphCode getIconCode()
    {
        return iconCode;
    }

    @Override
    protected void paintComponent(Graphics g1)
    {
        Graphics2D g = (Graphics2D) g1;
        g.setColor(isEnabled() ? (hover ? hoverColor : color) : disabledColor);
        g.drawGlyphVector(vector, (float) -size.getX(), (float) -size.getY());
    }

    @Override
    public Dimension getMinimumSize()
    {
        return size.getBounds().getSize();
    }

    @Override
    public Dimension getPreferredSize()
    {
        return size.getBounds().getSize();
    }
}

1
不再使用JComponent的MouseEvents,而是使用没有装饰的JButton,并且使用ButtonModel的ChangeListener。 - mKorbel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接