Visualizzazione dei risultati da 1 a 7 su 7

Discussione: Recupero altezza di un carattere

  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2004
    Messaggi
    51

    Recupero altezza di un carattere

    Salve,
    Avrei bisogno di conoscere l'altezza del carattere per dimensionare il JComponent, ma non c'è modo di recuperare questo dato. All'interno del metodo paintComponent grazie a FontMetric l'altezza viene ottenuta e messa nella variabile charH regolarmente visualizzata sul monitor. Ora perché quando vado a recuperare il valore di charH con il metodo getCharH() mi da 0!? Eppure la variabile charH è visibile nella classe. Del resto non c'è modo di usare un'oggetto Graphics al di fuori del metodo paintComponent in quanto classe Graphics è astratta e quindi non istanziabile.
    Grazie per l'eventuale aiuto.

    codice:
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import javax.swing.JComponent;
    import java.awt.Font;
    import javax.swing.JFrame;
    
    
    public class Metric extends JFrame {
        private int ft;
        public Metric() {        
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);             
            setLayout(null);
            setSize(200, 100);
            setLocationRelativeTo(null);
            
            fMet fmt = new fMet();
            fmt.setSize(100,30);
            ft=fmt.getCharH();
            System.out.println("H: " + ft);
            add(fmt);
            setVisible(true);
        }
    
    
        public static void main(String args[]) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new Metric();
                }
            });
        }    
    }
    
    
    class fMet extends JComponent{
        private int chrH;
        private String str="A";
    
    
        public void paintComponent(Graphics g){        
               super.paintComponent(g);
               Graphics2D g2D = (Graphics2D) g;
               
               FontMetrics fm=g2D.getFontMetrics();            
               chrH = fm.getHeight();
               System.out.println("chrH: " + chrH);
               g2D.setFont(new Font("Tahoma", 1, 12));
               g2D.drawString(str, 50, 30);
           }
           public int getCharH(){       
               return(chrH);
          }      
    }

  2. #2
    Quote Originariamente inviata da cersil Visualizza il messaggio
    Ora perché quando vado a recuperare il valore di charH con il metodo getCharH() mi da 0!?
    Perché quando esegui questo pezzo

    fMet fmt = new fMet();
    fmt.setSize(100,30);
    ft=fmt.getCharH();

    Il paintComponent NON è ancora stato chiamato. Quindi chrH è ancora al suo valore di "default" (0).

    Quote Originariamente inviata da cersil Visualizza il messaggio
    in quanto classe Graphics è astratta e quindi non istanziabile.
    Non vuol dire niente.
    Andrea, www.andbin.net – Senior Java developer – SCJP 5 (91%) – SCWCD 5 (94%)
    Il mio blog sulla programmazione

  3. #3
    Utente di HTML.it
    Registrato dal
    Feb 2004
    Messaggi
    51
    Ho provato a chiamare ft=fmt.getCharH(); dopo add(fmt); dopo setVisible(true); ma sempre zero da. Quando viene chiamato il metodo paintComponent? Dove devo posizionare la chiamata al metodo fmt.getCharH() per poterne avere il valore? Ci sarà un punto dove il metodo paintComponent è stato chiamato in modo che possa avere il dato. Ma quale?
    Sempre grazie.

  4. #4
    Quote Originariamente inviata da cersil Visualizza il messaggio
    Ho provato a chiamare ft=fmt.getCharH(); dopo add(fmt);
    Neanche.

    Quote Originariamente inviata da cersil Visualizza il messaggio
    dopo setVisible(true);
    No, neanche questo.

    Quote Originariamente inviata da cersil Visualizza il messaggio
    Quando viene chiamato il metodo paintComponent?
    Ben dopo. Dopo che quel tuo costruttore è terminato, dopo che il controllo è tornato al framework, dopo che il framework si è "accorto" che c'è un evento di ridisegno per quel tuo componente. Non è un tempo "lungo" (si tratta di una manciata di millisecondi) ma avviene appunto dopo.

    Quote Originariamente inviata da cersil Visualizza il messaggio
    Dove devo posizionare la chiamata al metodo fmt.getCharH() per poterne avere il valore?
    Non serve, non devi in quel modo. Non va bene aspettare il paintComponent.

    Ti serve invece il

    public FontMetrics getFontMetrics(Font font)

    che tutti i componenti hanno.

    E non so esattamente cosa vuoi fare ma se devi calcolare es. il preferred size o qualcosa del genere, tale logica andrebbe incapsulata all'interno del componente, non fatta all'esterno.
    Ultima modifica di andbin; 12-03-2018 a 14:30
    Andrea, www.andbin.net – Senior Java developer – SCJP 5 (91%) – SCWCD 5 (94%)
    Il mio blog sulla programmazione

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2004
    Messaggi
    51
    Grazie sempre gentilissimo.
    Ho provato così e funziona:
    codice:
            Font font=new Font("Arial", 1,12);
            FontMetrics fm= getFontMetrics(font);
            int chrH2 = fm.getHeight();
            System.out.println("chrH2: " + chrH2);
    Ma se volessi sapere l'altezza del font di default? Ho provato così ma Font ftt=getFont(); mi da Null!
    codice:
            Font ftt=getFont();
            FontMetrics fm= getFontMetrics(ftt);
            int chrH2 = fm.getHeight();
            System.out.println("chrH2: " + chrH2);
    Grazie ancora per la pazienza.

  6. #6
    Quote Originariamente inviata da cersil Visualizza il messaggio
    Ma se volessi sapere l'altezza del font di default?
    Premessa: in java.awt.Component (dove ci sono le proprietà "base", es. font, foreground ecc..) i metodi getFont(), getForeground() e altri sono implementati concettualmente così: se il componente ha un proprio font/foreground/ecc... allora restituisce quello e basta. Altrimenti se non ce l'ha, lo chiede al parente "strutturale" (il contenitore, che a sua volta potrebbe chiederlo al proprio parente, ecc...).

    Il tuo componente non ha un font predefinito, perché non ha un UI object (che per gli altri componenti JLabel, JButton ecc... viene dato dal Look&Feel impostato). Quindi il font arriva a chiederlo più in alto nella parentela strutturale.

    Quando fai:

    fMet fmt = new fMet();

    il componente non ha ancora un parente strutturale.
    Ma quando fai:

    add(fmt);

    il tuo componente diventa parte della struttura e quindi ha un parente. Ora, c'è sicuramente almeno un parente che ha un font predefinito. Il content-pane del JFrame è per default materialmente un JPanel, che ha di certo un font predefinito (dal L&F). Quindi dopo che hai aggiunto il tuo componente, esso "eredita" il font dal content-pane.


    Detto questo, vedi questo esempio che ho scritto al volo. Definisce una "mia" label, che è proprio solo un "giocattolo" (ci vorrebbe ben altro per farla "bene") ma ti può dare l'idea:

    codice:
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Insets;
    
    import javax.swing.BorderFactory;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    
    public class FrameProvaMyLabel extends JFrame {
        public FrameProvaMyLabel() {
            super("Prova");
    
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setSize(500, 400);
            setLocationRelativeTo(null);
            setLayout(new FlowLayout());
    
            MyLabel label1 = new MyLabel("Prova");
            label1.setBorder(BorderFactory.createLineBorder(Color.RED, 1));
            add(label1);
    
            MyLabel label2 = new MyLabel("abcdefghijklmnopqrstuvwxyz");
            label2.setBorder(BorderFactory.createLineBorder(Color.MAGENTA, 5));
            add(label2);
    
            MyLabel label3 = new MyLabel("Ciao");
            label3.setForeground(Color.RED);
            label3.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 40));
            label3.setBorder(BorderFactory.createMatteBorder(3, 8, 3, 8, Color.BLUE));
            add(label3);
    
            MyLabel label4 = new MyLabel("Hello");
            label4.setPreferredSize(new Dimension(100, 40));
            label4.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            add(label4);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new FrameProvaMyLabel().setVisible(true);
                }
            });
        }
    }
    
    
    class MyLabel extends JComponent {
        private String label;
    
        public MyLabel(String label) {
            this.label = label;
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
    
            Insets insets = getInsets(null);
            FontMetrics fm = g.getFontMetrics();
    
            int x = insets.left;
            int y = insets.top + fm.getAscent();
    
            g.drawString(label, x, y);
        }
    
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            }
    
            Insets insets = getInsets(null);
            FontMetrics fm = getFontMetrics(getFont());
    
            int dx = insets.left + insets.right;
            int dy = insets.top + insets.bottom;
    
            int sw = fm.stringWidth(label);
            int sh = fm.getHeight();
    
            return new Dimension(sw+dx, sh+dy);
        }
    
        @Override
        public Dimension getMinimumSize() {
            if (isMinimumSizeSet()) {
                return super.getMinimumSize();
            }
    
            return getPreferredSize();
        }
    
        @Override
        public Dimension getMaximumSize() {
            if (isMaximumSizeSet()) {
                return super.getMaximumSize();
            }
    
            return getPreferredSize();
        }
    }

    Ho usato un FlowLayout, che "rispetta" il preferred size dei componenti. Le prime 3 MyLabel hanno un preferred size calcolato. La quarta MyLabel ha un preferred size imposto esplicitamente.
    Andrea, www.andbin.net – Senior Java developer – SCJP 5 (91%) – SCWCD 5 (94%)
    Il mio blog sulla programmazione

  7. #7
    Utente di HTML.it
    Registrato dal
    Feb 2004
    Messaggi
    51
    Grazie andbin,
    vorrei sapere 1/1000000 di quello che sai.
    Ciao

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2018 vBulletin Solutions, Inc. All rights reserved.