java - GraphicsEnvironment#getAvailableFontFamilyNames() 后的奇怪字体行为?

标签 java fonts awt

我刚刚遇到了 Java 字体类的一个非常奇怪的行为。

如果我像这样创建“Verdana”系列的普通字体,

Font font = new Font("Verdana", Font.PLAIN, 12);

我希望这种字体是一种非粗体字体,它引用了我系统上安装的普通“Verdana”字体。我使用的是Windows 7,所以对应的字体应该是“Windows/Fonts”文件夹下的“verdana.ttf”。

虽然这似乎有效,但如果我调用实例化的字体会改变其行为

GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

在使用字体之前(即在字体内部绑定(bind)到任何系统字体之前)。在这种情况下,字体似乎引用了我系统上的“Verdana Bold”字体(“verdanab.ttf”)。

这里是一些测试代码,重现了这个问题:

import java.awt.Font;
import java.awt.GraphicsEnvironment;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class JavaFontBug {

    public static void main(String[] args) {

        boolean enableStrangeBug = false;
        Font font = new Font("Verdana", Font.PLAIN, 12);

        String text;
        if (enableStrangeBug) {
            // this line enables the bug:
            GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
            text = "Some Bold Text?!";
        } else{
            text = "Some Text";
        }

        System.out.println("Font: " + font);
        System.out.println("Font name: " + font.getFontName());

        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label = new JLabel(text);
        label.setFont(font);
        frame.getContentPane().add(label);
        frame.pack();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                frame.setVisible(true);
            }
        });
    }

}

如果 enableStrangeBug 设置为 false,将显示一个标签,其中显示“Some Text”和预期的普通“Verdana”字体。输出是:

Font: java.awt.Font[family=Verdana,name=Verdana,style=plain,size=12]
Family: Verdana
Name: Verdana
Font name: Verdana
PS name: Verdana

如果 enableStrangeBug 在另一方面设置为 true,标签字体似乎是“Verdana Bold”并且输出是:

Font: java.awt.Font[family=Verdana,name=Verdana,style=plain,size=12]
Family: Verdana
Name: Verdana
Font name: Verdana Bold
PS name: Verdana-Bold

我很确定这是一个错误,但我想知道这里的其他人是否在不同的系统上遇到过相同的行为。我使用的是 Windows 7,Java 7 和 Java 8 的行为相同。以下 Verdana 字体安装在我的“字体”文件夹中:verdana.ttf、verdanab.ttf、verdanai.ttf 和 verdanaz.ttf。

我第一次遇到这个问题是在为与描述的字体相似的字体开发 JComboBox 时 here ,它遇到同样的问题:JComboBox 的初始元素通过调用 GraphicsEnvironment#getAvailableFontFamilyNames() 进行初始化,这导致弹出窗口中的某些字体显示为粗体,尽管它们应该显示作为纯字体。

这里有没有人知道这个问题的解决方法,所以 this answer 中的 JComboBox为所有已安装的字体系列使用正确的纯字体进行初始化?

另外:有谁知道导致这个问题的原因吗?它似乎与“Verdana”字体没有直接关系,因为例如“Tahoma”字体系列在我的系统上也有同样的问题。另一方面,“Times New Roman”或“Arial”字体系列似乎工作正常......


更新

我刚刚找到了一个肮脏的解决方法——如果在 Java 类中包含以下静态初始化,错误就会神奇地消失:

static{
    for (Font f : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) {
        f.getPSName();
    }
}

但由于此解决方法与错误本身一样奇怪,我很乐意接受任何比这个更好的解决方案和/或更多信息的答案。

最佳答案

参见 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7083197 错误报告包含对问题如何发生的解释,但没有解决方法。

关于java - GraphicsEnvironment#getAvailableFontFamilyNames() 后的奇怪字体行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23470604/

相关文章:

java - 如何修改 JTextPane 中的字母间距?

css - 为什么我的 FontSquirrel 字体不起作用?

Java > 在现有图像上绘制多个矩形

java - Matcher.quoteReplacement 与 preparedstatement

java - 数据库问题

css - @font-face 用于网站上的所有字体

java - 对于一个类中的多个操作,哪个更好? actionPerformed() 中的匿名内部类或 if 语句?

java - AWT 绘画工具像素不完美

java - 游戏时长算法

java - Apache Camel : Is there any way to set a message to fault without injecting the exchange in a bean method?