2014-08-28 32 views
9

Tôi gặp sự cố khi hiển thị các hình tượng nhất định từ bộ sưu tập FontAwesome trong các nút trong Swing JToolBar. Đây là một ảnh chụp màn hình để minh họa (chú ý rằng nút trên cùng trong thanh công cụ ở phía bên tay phải không phải là một biểu tượng đẹp nhưng thay vào đó cho thấy ba hình chữ nhật trống):Một số phông chữ FontAwesome không hiển thị trong các nút Java Swing JToolBar

Screenshot to illustrate the problem

Mã này để tái sản xuất này (ít nhất là trên máy Mac của tôi) là:

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.Font;![enter image description here][2] 
import java.awt.FontFormatException; 
import java.io.IOException; 
import java.io.InputStream; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JToolBar; 

public class TestFontAwesome { 

    public static void main(String[] args) { 
     new TestFontAwesome(); 
    } 

    public TestFontAwesome() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try (InputStream is = TestFontAwesome.class.getResourceAsStream("/fontawesome-webfont_old.ttf")) { 
        Font font = Font.createFont(Font.TRUETYPE_FONT, is); 
        font = font.deriveFont(Font.PLAIN, 24f); 

        JToolBar toolBar = new JToolBar(JToolBar.VERTICAL); 
        JButton button1 = new JButton("\uf00e"); 
        button1.setFont(font); 
        toolBar.add(button1); 
        JButton button2 = new JButton("\uf01e"); 
        button2.setFont(font); 
        toolBar.add(button2); 
        JFrame frame = new JFrame("Testing"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.setLayout(new BorderLayout()); 
        frame.add(new JButton("Irrelevant content...")); 
        frame.add(toolBar, BorderLayout.EAST); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } catch (IOException | FontFormatException exp) { 
        exp.printStackTrace(); 
       } 
      } 
     }); 
    } 

} 

Tôi đã thử một vài điều sau: (1) Sử dụng các phiên bản khác nhau của tệp FontAwesome.ttf, không thay đổi; (2) Thử các phiên bản JDK khác nhau, không thay đổi; (3) Hiển thị cùng một ký tự trong một JButton thường xuyên, điều này làm việc như bạn có thể thấy trong hình bên dưới (vì vậy đây rõ ràng không phải là một số vấn đề với các file font):

Screenshot to show it works in a regular JButton

tôi thử nghiệm trên một tổ chức phi -Retina Mac và tất cả mọi thứ hoạt động, vì vậy tôi tự hỏi nếu điều này là một cái gì đó cụ thể cho màn hình Retina. Nếu bất cứ ai có bất cứ đề nghị tôi muốn đánh giá cao nghe từ bạn, cảm ơn.

Mã cho chỉ ví dụ JButton (rằng hoạt động tốt) là:

import java.awt.EventQueue; 
import java.awt.FlowLayout; 
import java.awt.Font; 
import java.awt.FontFormatException; 
import java.io.IOException; 
import java.io.InputStream; 
import javax.swing.JButton; 
import javax.swing.JFrame; 

public class TestFontAwesome2 { 

    public static void main(String[] args) { 
     new TestFontAwesome2(); 
    } 

    public TestFontAwesome2() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try (InputStream is = TestFontAwesome.class.getResourceAsStream("/fontawesome-webfont_old.ttf")) { 
        Font font = Font.createFont(Font.TRUETYPE_FONT, is); 
        font = font.deriveFont(Font.PLAIN, 24f); 

        JButton button1 = new JButton("\uf00e"); 
        button1.setFont(font); 
        JButton button2 = new JButton("\uf01e"); 
        button2.setFont(font); 
        JFrame frame = new JFrame("Testing"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.setLayout(new FlowLayout()); 
        frame.add(new JButton("Irrelevant content...")); 
        frame.add(button1); 
        frame.add(button2); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } catch (IOException | FontFormatException exp) { 
        exp.printStackTrace(); 
       } 
      } 
     }); 
    } 

} 
+1

JTollBar sử dụng BoxLayout (tối thiểu, kích thước ưa thích, kích thước ưa thích được sử dụng cho LayoutManager), sau đó có mọi thứ có thể trong trường hợp Font có thể ' t trả về đúng widht, cùng một vấn đề có thể bằng cách sử dụng FlowLayout cho JFrame (chỉ PreferredSize), thêm thẻ osx cho trashgod – mKorbel

+0

[xem sự khác biệt trong trường hợp Phông chữ được cài đặt trong Hệ điều hành Gốc và được tải tại thời gian chạy] (http: // stackoverflow .com/questions/18461331/ttf-và-otf-phiên bản-của-nguồn-sans-pro-là-khác nhau-hiển thị-in-swing-nimb), theo mặc định không có vấn đề gì để kiểm tra (theo pixel: -) cho String widht bằng cách sử dụng SwingUtilities # computeStringWidth (FontMetrics fm, String str), ei – mKorbel

+0

btw và Retina không nhiều hơn 2 lần so với pixel do GPU thực sự sử dụng để hiển thị ngữ cảnh, thiết lập độ phân giải hiệu quả theo pixel – mKorbel

Trả lời

4

tôi nghĩ rằng vấn đề là ComponentUi
Phương tiện trong đặc biệt: ToolbarUi hoặc ButtonUi (-Implementation).

Thanh công cụUi (và ButtonUi) là các lớp trừu tượng, được triển khai trong Chế độ xemAndFeel được chọn của bạn.
Việc triển khai có thể hoàn toàn khác nhau đối với mỗi LookAndFeel.
Một số triển khai làm bỏ qua một số cài đặt "người dùng" như ví dụ: Phông chữ hoặc Màu.

JButtons có thể sử dụng Ui-Implementation khác với các nút được thêm vào JToolBars!
Và việc triển khai này có thể bỏ qua cài đặt Phông chữ của bạn.

Xem cho thực hiện ví dụ ButtonUi (chỉ là một phần của) trong MetalLookAndFeel

public void update(Graphics g, JComponent c) { 
    AbstractButton button = (AbstractButton)c; 
    if ((c.getBackground() instanceof UIResource) && 
      button.isContentAreaFilled() && c.isEnabled()) { 
     ButtonModel model = button.getModel(); 
     if (!MetalUtils.isToolBarButton(c)) { 
      if (!model.isArmed() && !model.isPressed() && 
        MetalUtils.drawGradient(
        c, g, "Button.gradient", 0, 0, c.getWidth(), 
        c.getHeight(), true)) { 
       paint(g, c); 
       return; 
      } 
     } 
... 

Ở đây bạn có thể thấy các hành vi khác nhau khi MetalUtils.isToolbarButton

Bạn phải kiểm tra LookAndFeel của bạn Hành vi thực hiện.
(Có thể cũng có một Triển khai khác, tùy thuộc vào độ phân giải màn hình)

+0

Tôi nghĩ rằng bạn đang đúng rằng nó có thể là một cái gì đó về mật độ màn hình - giao diện người dùng có thể tìm kiếm một glyph khác nhau dựa trên mật độ màn hình tăng gấp đôi của Retina. Có một tệp ttf FontAwesome khác hoặc mới hơn cho màn hình có mật độ cao không? –

+0

Tôi nghi ngờ rằng vấn đề là với các tập tin TTF, vì tất cả các glyphs hiển thị chính xác trong ví dụ JButton. –

+1

Chắc chắn giao diện người dùng là một yếu tố. Tôi đã thử với Metal và Nimbus LAFs và biểu tượng hiển thị chính xác, do đó, nó chỉ là (Mac) hệ thống nhìn & cảm thấy có vấn đề. –

Các vấn đề liên quan