JTextPane/JTextField奇怪的行为与稀有字符

n00*_*ter 5 java swing jtextpane jtextfield

我在JTextPane/JTextField中发现了一个奇怪的错误(或者在它们下面的字体渲染中的某个地方).我想知道是否有其他人遇到过这种情况并且可能有解决方案.

我试图在JTextPane中显示一些"特殊"或罕见的字符,并且一旦我更改了JTextField的字体(与JTextPane完全无关!),JTextPane就会"分解",并且不再显示这些字符字符.

这应该更好地解释我的意思:

public class Scrap {

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(200, 200);
    frame.setLayout(new BorderLayout());

    JTextField field = new JTextField();

    // Uncomment this line... and the JTextPane nor the JTextField
    // no longer display the characters
    // field.setFont(new Font("Arial", Font.PLAIN, 14));

    frame.add(field, BorderLayout.SOUTH);

    JTextPane textPane = new JTextPane();
    textPane.setFont(new Font("Arial", Font.PLAIN, 14));

    JScrollPane scroll = new JScrollPane(textPane);
    frame.add(scroll, BorderLayout.CENTER);

    StyledDocument doc = (StyledDocument) textPane.getDocument();

    try {
        String str = "? ?? ?";

        doc.insertString(doc.getLength(), str, null);

    } catch (BadLocationException e) {
        e.printStackTrace();
    }

    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
}
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是问题的一个更好的例子.它似乎与Font的大小有关.移动滑块,您会注意到大小14不会渲染字形,而14恰好是JTextField字体的大小.

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.*;
import java.awt.*;

public class Scrap {

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(600, 200);
    frame.setLayout(new BorderLayout());

    final JTextField field = new JTextField(10);

    final JTextPane textPane = new JTextPane();

    StyledDocument doc = (StyledDocument) textPane.getDocument();

    JPanel panel = new JPanel();
    frame.add(panel, BorderLayout.SOUTH);

    // Set the Font of the JTextField, and the JTextPane
    // no longer displays the text of that size correctly...

    int changeMe = 14;

    field.setFont(new Font("Tahoma", Font.PLAIN, changeMe));

    // If we change the Font Family, the problem goes away...
    // field.setFont(new Font("Dialog", Font.PLAIN, 14));

    panel.add(field);

    final JLabel label = new JLabel();

    final JSlider slider = new JSlider(6, 32);
    slider.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            textPane.setFont(new Font("Tahoma", Font.PLAIN, slider.getValue()));

            textPane.selectAll();

            SimpleAttributeSet attr = new SimpleAttributeSet();
            StyleConstants.setFontSize(attr, slider.getValue());
            textPane.setCharacterAttributes(attr, true);

            label.setText("" + slider.getValue());
        }
    });

    slider.setValue(14);

    panel.add(slider);

    panel.add(label);

    JScrollPane scroll = new JScrollPane(textPane);
    frame.add(scroll, BorderLayout.CENTER);

    Style s = doc.addStyle("test", null);

    try {
        String str = "? ?? ?";

        doc.insertString(doc.getLength(), str, doc.getStyle("test"));

    } catch (BadLocationException e) {
        e.printStackTrace();
    }

    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
}
}
Run Code Online (Sandbox Code Playgroud)

Laf*_*ica 2

当我尝试制作一个必须支持多种语言(包括具有“非标准”字符的语言,例如中文)的应用程序时,我遇到了类似的问题。我曾经将小部件的字体设置为Arial,但遇到了问题。以下解决方案解决了我的问题,但可能无法解决您的问题。

当 Java 遇到无法显示的特定字符集中的字符时,它有一个后备机制。它可以使用 JRE 提供的 fontconfig.properties 文件进行配置(该文件最初提供为“fontconfig.properties.src”,您必须手动重命名它)。

当您强制使用不在DialogSerifSansSerifMonospaced之间DialogInput的字体时,如果当前字符集(在您的情况下为 Arial)无法表示您尝试在屏幕上绘制的字符(或字形),则 Java 无法使用其他字符集。

如果您查看 fontconfig.properties.src 文件,您将看到它有许多针对多种类型字体的条目(例如Dialog.plainSerif.bold等)。当上面的字体无法显示特定字形时,这些是实际使用的后备字体。因此,将小部件的字体设置为Font.DIALOG允许 Java 尝试使用字体列表来显示字符。

更多信息请访问 Oracle 网站(此处针对 Java 7)。请注意,Oracle 不正式支持使用 fontconfig.properties。