2014-08-28 2 views
9

Ho riscontrato un problema durante la visualizzazione di determinati glifi dalla raccolta FontAwesome nei pulsanti in una SwToolBar. Ecco uno screenshot per illustrare (notare che il pulsante in alto nella barra degli strumenti sul lato destro non è l'icona di un bello, ma mostra invece tre rettangoli vuoto):Alcuni glifi FontAwesome non vengono visualizzati in Java Swing JToolBar buttons

Screenshot to illustrate the problem

Il codice per riprodurre questo (almeno sul mio Mac) è:

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

} 

ho provato un paio di cose: (1) con diverse versioni del file FontAwesome.ttf, nessun cambiamento; (2) Provare diverse versioni di JDK, nessuna modifica; (3) Visualizzazione lo stesso personaggio in un JButton regolare, questo funziona come potete vedere nello screenshot seguente (quindi questo non è chiaramente qualche problema con il file di font):

Screenshot to show it works in a regular JButton

ho testato su un non -Retina Mac e tutto funziona, quindi mi chiedo se questo è qualcosa di specifico per il display Retina. Se qualcuno ha qualche suggerimento, mi farebbe piacere sentirti, grazie.

Il codice per l'unico esempio JButton (che funziona bene) è:

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 utilizza BoxLayout (dimensioni min, max e preferite, la dimensione preferita viene utilizzata per LayoutManager), quindi c'è tutto il possibile nel caso che Font possa ' t restituisce la larghezza corretta, lo stesso problema può essere usando FlowLayout per JFrame (solo PreferredSize), aggiunto tag osx per trashgod – mKorbel

+0

[vedere la differenza nel caso in cui Font sia installato nel sistema operativo nativo e caricato in fase di runtime] (http: // stackoverflow .it/questions/18461331/ttf-and-otf-versions-of-source-sans-pro-sono-different-display-in-swing-nimb), per impostazione predefinita non c'è un problema da testare (in pixel: -) per la larghezza delle stringhe usando SwingUtilities # computeStringWidth (FontMetrics fm, String str), ei – mKorbel

+0

btw e Retina non sono circa 2 volte più pixel come è realmente utilizzato dalla GPU per il rendering del contesto, impostando la risoluzione effettiva in pixel – mKorbel

risposta

4

penso che il problema è il ComponentUI
significa in particolare: ToolbarUi o ButtonUi (-Attuazione).

ToolbarUi (e ButtonUi) sono classi astratte, che sono implementate nello selezionato.
L'implementazione può essere completamente diversa per ogni LookAndFeel.
Alcune implementazioni ignorano alcune impostazioni "utente" come ad esempio Font o Colore.

I JButton possono utilizzare una diversa implementazione dell'interfaccia utente rispetto ai pulsanti aggiunti a JToolBars!
E questa implementazione può ignorare le impostazioni dei caratteri.

Vedere per esempio di implementazione ButtonUi (solo una parte del) in 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; 
      } 
     } 
... 

Qui potete vedere il comportamento diverso quando MetalUtils.isToolbarButton

Devi controllare il tuo LookAndFeel Comportamento di implementazione.
(Forse c'è anche un'implementazione diversa, a seconda della risoluzione dello schermo)

+0

Penso che tu abbia ragione sul fatto che probabilmente è qualcosa sulla densità dello schermo - l'interfaccia utente potrebbe essere alla ricerca di un glifo diverso basato sulla densità dello schermo raddoppiata del Retina. C'è un file ttf FontAwesome diverso o più recente per i display ad alta densità? –

+0

Dubito che il problema sia con il file TTF, dal momento che tutti i glifi vengono visualizzati correttamente nell'esempio JButton. –

+1

Certamente il delegato UI è un fattore. Ho provato con Metal e Nimbus LAF e l'icona viene visualizzata correttamente, quindi è solo l'aspetto del sistema (Mac) che ha il problema. –