在Java控制台中出现Unicode特殊字符但不在Swing中

问题描述:

我试图向JFrame内部的JLabel添加一些高范围Unicode字符,但它们只显示为框,尽管使用了已知的支持字体。但是,当我将这些相同的字符打印到Eclipse控制台时,它们显示得很好。这是我的代码,“框架”是我的JFrame,“textField1”是我的JLabel。摩纳哥字体是Eclipse控制台使用相同的字体,并且知道要支持这种Unicode字符:在Java控制台中出现Unicode特殊字符但不在Swing中

JFrame frame = new JFrame(); 
JLabel textField1 = new JLabel(); 
frame.add(textField1); 
frame.setFocusable(true); 
frame.setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS)); 
frame.setPreferredSize(new Dimension(1000, 500)); 
frame.requestFocusInWindow(); 
frame.textField1.setFont(new Font("Monaco", Font.PLAIN, 11)); 
frame.textField1.setText("\uD83C\uDF2D"); 
frame.pack(); 
frame.setVisible(true); 

我已经试过的JLabel设置为许多不同的字体,但所有的变化是相对形状“缺少的字符”框。但是,如果我打印此:

System.out.println("\uD83C\uDF2D"); 

字符在控制台中按预期打印。是否有一些编码问题阻止这些符号在Swing中运行?

+2

最常见的原因是字体不支持字符的显示 – MadProgrammer

+0

@MadProgrammer是的,但正如我所说我100%确定这个字体支持字符,我查了一下,加上它是控制台相同的字体我说哪个显示它完美。我也尝试过多种已知支持这个字符的字体,但无济于事。 – zooksman

+1

我不相信摩纳哥字体有字符(['HOT DOG'(U + 1F32D)](http://www.fileformat.info/info/unicode/char/1f32d/index.htm))。控制台更可能自动切换到另一种字体以显示特殊字符。如果您将该字符粘贴到此页面中,您将看到它不起作用:https://www.myfonts.com/fonts/apple/monaco/ – Andreas

Font.canDisplayUpTo(String)方法在这里是你的朋友。这就是它如何用来创建支持文本的字体的组合。

 String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment(). 
       getAvailableFontFamilyNames(); 
     System.out.println(fonts.length + " font families installed"); 
     Vector<String> supportedFonts = new Vector<>(); 
     for (String fontName : fonts) { 
      Font f = new Font(fontName, Font.PLAIN, 1); 
      if (f.canDisplayUpTo(text)<0) { 
       System.out.println(fontName); 
       supportedFonts.add(fontName); 
      } 
     } 
     fontComboBox = new JComboBox(supportedFonts); 

这说明此计算机上安装字体的数量,其次是将显示文本(字符一个热狗)的字体列表。

225 font families installed 
Segoe UI Emoji 
Segoe UI Symbol 

这是产生上述输出,以及显示GUI,它允许用户将所有支持给定的Unicode字符(多个)的字体之间进行选择的源代码:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import java.util.Vector; 

public class FontCheck { 

    private JComponent ui = null; 

    private final String text = "\uD83C\uDF2D"; 
    private JComboBox fontComboBox; 
    private JTextField outputField = new JTextField(text, 5); 

    FontCheck() { 
     initUI(); 
    } 

    public void initUI() { 
     if (ui!=null) return; 

     ui = new JPanel(new BorderLayout(4,4)); 
     ui.setBorder(new EmptyBorder(4,4,4,4)); 

     ui.add(outputField); 
     ui.add(getToolBar(), BorderLayout.PAGE_START); 

     refreshFont(); 
    } 

    private JToolBar getToolBar() { 
     JToolBar tb = new JToolBar(); 
     tb.setLayout(new FlowLayout()); 

     String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment(). 
       getAvailableFontFamilyNames(); 
     System.out.println(fonts.length + " font families installed"); 
     Vector<String> supportedFonts = new Vector<>(); 
     for (String fontName : fonts) { 
      Font f = new Font(fontName, Font.PLAIN, 1); 
      if (f.canDisplayUpTo(text)<0) { 
       System.out.println(fontName); 
       supportedFonts.add(fontName); 
      } 
     } 
     fontComboBox = new JComboBox(supportedFonts); 
     ActionListener refreshListener = new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       refreshFont(); 
      } 
     }; 
     fontComboBox.addActionListener(refreshListener); 

     tb.add(fontComboBox); 
     return tb; 
    } 

    private void refreshFont() { 
     String fontName = fontComboBox.getSelectedItem().toString(); 
     Font f = new Font(fontName, Font.PLAIN, 60); 
     outputField.setFont(f); 
    } 

    public JComponent getUI() { 
     return ui; 
    } 

    public static void main(String[] args) { 
     Runnable r = new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (Exception useDefault) { 
       } 
       FontCheck o = new FontCheck(); 

       JFrame f = new JFrame(o.getClass().getSimpleName()); 
       f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       f.setLocationByPlatform(true); 

       f.setContentPane(o.getUI()); 
       f.pack(); 
       f.setMinimumSize(f.getSize()); 

       f.setVisible(true); 
      } 
     }; 
     SwingUtilities.invokeLater(r); 
    } 
} 
+0

以防万一它很重要,如果我没有安装这些fon't,我得到NPE: 的EventQueue-0" 显示java.lang.NullPointerException \t在test.FontCheck.refreshFont(FontCheck.java:70) \t在test.FontCheck.initUI(FontCheck.java:37) \t at test.FontCheck。(FontCheck.java:23)' – Optional

+1

*“以防万一,如果我没有安装它们,您理解代码的问题,其中**不包括卸载的字体**,并且**不会将NPE **与源代码完全一致如上所示 –

+0

如何安装新的不支持的字体?是不是重要的是@安德鲁 - 汤普森?然而,一点点的申请还可以解决OP的问题。 – Optional

第一件事第一件事。

1)\uD83C\uDF2D在Moncaco字体上不受支持。

2)您可以检查支持该字符在fileformat

3)支持的字体,似乎对这个人物的工作字体,列有:LastResport, Symbola and Unifont Upper。请参阅link

现在您如何在Java中支持它?下载font,将其设置为标签并使用它,如下所示。

import java.awt.Dimension; 
import java.awt.Font; 
import java.io.File; 
import java.net.URI; 
import javax.swing.BoxLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.WindowConstants; 

public class FrameMain1 { 

    public static void main(String[] args) throws Exception { 

     File fontFile = new File(new URI("file:///D:/tmp/Symbola.ttf")); 
     Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile); 
     font = font.deriveFont(Font.PLAIN, 24f); 
     JFrame frame = new JFrame(); 
     JLabel label1 = new JLabel("\uD83C\uDF2D"); 
     frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS)); 
     frame.add(label1); 
     frame.setFocusable(true); 
     //frame.setPreferredSize(new Dimension(1000, 500)); 
     frame.requestFocusInWindow(); 
     label1.setFont(font); 
     frame.add(label1); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

} 

See the image