JTextPane/JTextField具有稀有字符的奇怪行为 [英] JTextPane/JTextField strange behaviour with rare characters

查看:82
本文介绍了JTextPane/JTextField具有稀有字符的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've discovered a strange bug in JTextPane/JTextField (or somewhere in the font rendering underneath them). I wonder if anyone else has encountered the same and might have a solution for this.

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

I'm trying to display some "special" or rare characters in a JTextPane, and as soon as I change the font of the JTextField (which is completely unrelated to JTextPane!), the JTextPane "breaks up", and no longer displays these characters.

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

This should do a better job explaining what I mean:

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

这是问题的一个更好的例子.它似乎与字体的大小有关.移动Slider,您将注意到大小14如何不呈现字形,而14恰好是JTextField的Font的大小.

Here's a better example of the problem. It appears to be related to the size of the Font. Move the Slider and you'll notice how the size 14 does not render the glyphs, and 14 happens to be the size of the JTextField's Font.

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

推荐答案

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

I had a similar problem when I tried to make an application that would have to support multiple languages (including languages with "non-standard" characters, such as chinese). I used to set the font of my widgets to Arial, and had the problem. The following solution fixed my problem, but it might not fix yours.

Java遇到无法显示的特定字符集的字符时,都会有一个回退机制.可以使用JRE随附的fontconfig.properties文件进行配置(该文件最初以"fontconfig.properties.src"的形式提供,您必须手动重命名).

Java has a fallback mechanism whenever it encounters characters from specific charsets it can't display. It can be configured using the fontconfig.properties file, which is provided with the JRE (the file is originally provided as "fontconfig.properties.src", you have to manually rename it).

当您强制使用一种不在DialogSerifSansSerifMonospacedDialogInput中的字体时,如果当前的字符集是Java,则Java无法使用其他字符集(在您的情况下) Arial)不能代表您要在屏幕上绘制的字符(或字形).

When you force a font that isn't among Dialog, Serif, SansSerif, Monospaced or DialogInput, Java has no way to use a different charset if the current one (in your case Arial) cannot represent the character (or glyph) you are trying to draw on screen.

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

If you look at the fontconfig.properties.src file, you will see that is has many entries for many types of fonts (e.g. Dialog.plain, Serif.bold, etc). These are the actual fallback fonts to use whenever the fonts above cannot display a specific glyph. So, settings your widgets' font to let's say Font.DIALOG will allow Java to try a list of fonts to display your characters.

有关更多信息,请访问Oracle网站(此处为Java 7 ).请注意,Oracle尚未正式支持使用fontconfig.properties.

More information is available on Oracle's website (here for Java 7). Note that the use of fontconfig.properties isn't officially supported by Oracle.

这篇关于JTextPane/JTextField具有稀有字符的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆