Forrige avsnitt Neste avsnitt Start på kapittel om grafiske brukergrensesnitt

Fonter

En font definerer utseende og størrelse for tekst som skal skrives ut. For all tekst som skal tegnes ut i grafiske vinduer kan vi velge mellom mange forskjellige fonter og varianter av disse. Dersom vi ikke konkret foretar noe valg, vil det bli brukt en standardfont som er satt på forhånd. Hver font er i java definert som et Font-objekt. Font-klassen kan vi importere fra pakken java.awt. Den vanligste konstruktøren vi bruker for å opprette et Font-objekt har følgende signatur:

  public Font(String navn, int stil, int størrelse)

For parametrene har vi følgende valgmuligheter:

Det kan variere fra java-installasjon til java-installasjon hvilke fonter som virkelig er tilgjengelige. Dette har blant annet sammenheng med at det til fonter ofte er knyttet copyright-rettigheter, med krav til dem som bruker fontene om å betale royalty til rettighetshaverne. Det er imidlertid ofte med fonter som det er for eksempel med dyre parfymer, at det finnes billige etterlikninger. Etterlikningene har da som regel andre navn. For eksempel er på Windows-systemer fonten Arial en etterlikning av fonten Helvetica, fonten Times New Roman en etterlikning av Times Roman, og fonten Courier New en etterlikning av Courier.

For at det skal finnes en felles plattform når det gjelder fonter, er det i java definert noen såkalte logiske fonter, og det skilles mellom fysiske fonter og logiske fonter. De fysiske fontene er de "egentlige" fontene som svarer til det man virkelig kan se på trykk eller på skjerm. Java-plattformen definerer følgende fem logiske fonter:

  SansSerif
  Serif
  Monospaced
  Dialog
  DialogInput

De logiske fontene er ingen virkelige fonter. Isteden skal de på alle java-installasjoner være definert til å bli tilordnet fysiske fonter som virkelig er tilgjengelige på vedkommende system. Hvilke fonter dette er, kan være både plattform- og lokalitetsavhengig. Når man bruker en logisk font, kan derfor det synlige resultatet være plattform- og stedsavhengig. Bruker man derimot en fysisk font, har man garanti for utseendet. Men man har ingen garanti for at fonten virkelig er tilgjengelig på den plattformen som programmet kan komme til å bli kjørt på. Hvordan de logiske fontene virker på vår plattform skal vi se nærmere på i Eksempel 2 nedenfor.

Ønsket font kan settes ved kall på metoden setFont med ønsket Font-objekt som aktuell parameter. Metoden kan enten brukes på et Graphics-objekt (i tilfelle vi skal skrive tekst ved bruk av drawString), eller på en grafisk skjermkomponent, det vil si objekter av type JButton, JTextField, etc., for å velge font for teksten som komponenten skal vise på skjermen.

Eksempel 1: Fontstiler

Programmet Fontstiler.java som er gjengitt nedenfor, viser eksempler på opprettelse av forskjellige fonter, samt valg av farge ved hjelp av et dialogvindu av type JColorChooser. Det settes font og farge på et Graphics-objekt. Driverklasse for programmet finnes i fila FontstilerOgFarge.java. Når programmet kjøres, får man et vindu som ser ut på denne måten, etter at det er valgt en blåfarge for utskriften:

 1 import javax.swing.*;
 2 import java.awt.*;
 3 import java.awt.event.*;
 4
 5 public class Fontstiler extends JFrame
 6 {
 7    private String sitat = "Type faces - like people's faces - " +
 8       "have distinctive features indicating aspects of character.";
 9    private JButton fargevelger = new JButton( "Skift skrivefarge" );
10    private Color farge = Color.black;
11
12    public Fontstiler()
13    {
14      super( "Fontstiler og farge" );
15      fargevelger.addActionListener( new Knappelytter() );
16      Container c = getContentPane();
17      c.setLayout( new FlowLayout() );
18      c.add( fargevelger );
19      setSize( 800, 300 );
20      setVisible( true );
21    }
22
23    //Demonstrerer noen fonter av forskjellig type og størrelse.
24    public void paint( Graphics g )
25    {
26      super.paint( g );
27      g.setColor( farge );
28      g.setFont (new Font ("TimesRoman", Font.PLAIN, 12));
29      g.drawString (sitat, 10,100);
30      g.setFont (new Font ("TimesRoman", Font.BOLD, 14));
31      g.drawString (sitat, 10,120);
32      g.setFont (new Font ("Helvetica", Font.ITALIC, 16));
33      g.drawString (sitat, 10,140);
34      g.setFont (new Font ("Helvetica", Font.PLAIN, 18));
35      g.drawString (sitat, 10,160);
36      g.setFont (new Font ("Helvetica", Font.BOLD, 18));
37      g.drawString (sitat, 10,180);
38      g.setFont( new Font( "Serif", Font.BOLD + Font.ITALIC, 18 ) );
39      g.drawString( sitat, 10, 200 );
40    }
41
42    private class Knappelytter implements ActionListener
43    {
44       public void actionPerformed( ActionEvent e )
45       {
46         if ( e.getSource() == fargevelger )
47         {
48           farge = JColorChooser.showDialog(
49                   Fontstiler.this, "Velg en farge", farge);
50           if ( farge == null )
51             farge = Color.lightGray;
52
53           repaint();
54         }
55       }
56    }
57 }

Eksempel 2: Logiske fonter

Programvinduet LogiskeFonter2.java er en demonstrasjon av hvordan de logiske fontene virker på Windows-plattform. Blir programmet kjørt på en annen plattform, vil utseendet på utskriften (sannsynligvis) være noe annerledes. Programkoden er gjengitt nedenfor. Driverklasse for programmet finnes i fila Fonttest.java. Når programmet kjøres, får vi opp følgende vindu:

 1 import javax.swing.*;
 2 import java.awt.*;
 3
 4 //Viser hvordan de logiske fontnavnene blir avbildet.
 5 public class LogiskeFonter2 extends JFrame
 6 {
 7    public LogiskeFonter2()
 8    {
 9      super( "Logiske fonter" );
10      setSize( 750, 350 );
11      setVisible( true );
12    }
13
14    public void paint( Graphics g )
15    {
16      super.paint( g );
17      int linjeavstand = 50, x = 10, y = 100;
18
19      g.setFont ( new Font ( "SansSerif", Font.PLAIN, 30 ) );
20      g.drawString ( "SansSerif er en font uten serifer.", x,y);
21      y += linjeavstand;
22
23      g.setFont ( new Font ("Serif", Font.PLAIN, 30 ) );
24      g.drawString ("Serif. Bokstavene skal da ha serifer.", x,y);
25      y += linjeavstand;
26
27      g.setFont ( new Font ("Monospaced", Font.PLAIN, 30) );
28      g.drawString ("Monospaced gir alle tegn samme bredde.", x,y);
29      y += linjeavstand;
30
31      g.setFont ( new Font ("Dialog", Font.PLAIN, 30) );
32      g.drawString ("Dialog ser slik ut.", x,y);
33      y += linjeavstand;
34
35      g.setFont ( new Font ("DialogInput", Font.PLAIN, 30) );
36      g.drawString ("Og her er DialogInput.", x,y);
37    }
38 }

Merknad Hvilke fysiske fonter de logiske fontene blir tilordnet er bestemt av fila fontconfig.properties.src som befinner seg i jre/lib-underkatalogen til Java-installasjonen. På Windows-plattform blir Serif tilordnet Times New Roman, SansSerif og Dialog blir tilordnet Arial, mens Monospaced og DialogInput blir tilordnet Courier New.

Hvordan vite hvilke fonter som er tilgjengelige?

For å få en liste over alle tilgjengelige fonter på systemet man kjører et program på, kan man bruke instruksjonen

  Font[] fontliste =
           GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();

De returnerte fontene vil ha default-egenskaper og størrelse lik 1 punkt. For å kunne brukes må de derfor tilpasses, iallfall når det gjelder størrelse. Det kan gjøres ved å gjøre kall på Font-objektenes deriveFont-metode. De mest aktuelle versjonene å bruke av denne vil da være den som tar en float-parameter for fontstørrelse, og den som tar en int-parameter for fontstil. (Bruk de forhåndsdefinerte parameterverdiene som er nevnt ovenfor.) Det tilpassete Font-objektet får vi i retur fra deriveFont-metoden.

Instruksjonen

  String[] fontnavn = GraphicsEnvironment.
    	getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

gir oss en liste med navn på alle fontfamilier som er tilgjengelige på systemet.

Eksempel 3

Klassen Fontpanel gjengitt nedenfor definerer et tegnepanel der navnene på alle tilgjengelige fonter blir skrevet ut med den fonten som vedkommende font definerer. (Om bruk av paneler som tegnepanel, se notatet Panel brukt som tegneflate.) Til slutt blir det skrevet ut hva som er standardfont.

 1 import javax.swing.*;
 2 import java.awt.*;
 3
 4 public class Fontpanel extends JPanel
 5 {
 6   private Font[] fontliste;
 7
 8   public Fontpanel()
 9   {
10     fontliste =
11             GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
12   }
13
14   public Dimension getPreferredSize()
15   {
16     return new Dimension(2000, 700);
17   }
18
19   public void paintComponent( Graphics g )
20   {
21     super.paintComponent( g );
22     int xpos = 10, ypos = 20, linjeavst = 15;
23     int spaltebredde = 250;
24     g.drawString( "Tilgjengelige fonter:", xpos, ypos );
25     ypos += linjeavst;
26     Font standard = g.getFont();
27     int i;
28     int spaltehøyde = 40;
29
30     for ( i = 0; i < fontliste.length; i++ )
31     {
32       g.setFont( fontliste[ i ].deriveFont( 12.0F ) );
33       ypos += linjeavst;
34       g.drawString( fontliste[ i ].getFontName(), xpos, ypos );
35       if ( (i + 1) % spaltehøyde == 0 )
36       {
37         xpos += spaltebredde;
38         ypos =35;
39       }
40     }
41     g.setFont( standard );
42     ypos += linjeavst;
43     g.drawString("Standardfont: " + standard.getFontName(),xpos,ypos);
44   }
45 }

I vindusklassen Fontliste vist nedenfor blir det lagt inn et Fontpanel av typen beskrevet ovenfor. Driverklasse for programmet finnes i fila Fontlistetest.java.

 1 import javax.swing.*;
 2
 3 //Liste over tilgjengelige fonter
 4 public class Fontliste extends JFrame
 5 {
 6   private Fontpanel fontliste;
 7
 8   public Fontliste()
 9   {
10     super( "Fontliste" );
11     fontliste = new Fontpanel();
12     getContentPane().add(new JScrollPane(fontliste));
13     setSize(1000,700);
14     setVisible( true );
15   }
16 }

Fontmetrikker

Vi skal se litt nærmere på hvordan vi kan få tak i diverse måledata for en gitt font, samt også finne ut hvor stor plass en gitt tekst vil ta når den blir skrevet ut med en gitt font.

Måledata for en gitt font blir kalt metrikker for fonten. I Java er disse samlet i et objekt av type FontMetrics (i klassebibliotekets pakke java.awt). For å få tak i dette for en aktuell font, må vi bruke grafikk-konteksten til vedkommende komponent (det vil si Graphics-objektet som den er tilordnet, og som er parameter i paint-metoden). Instruksjonen

  FontMetrics metrikk = g.getFontMetrics();

gir metrikken for aktuell font (den som gjelder for øyeblikket), mens instruksjon

  FontMetrics metrikk = g.getFontMetrics(font);

gir metrikken for den fonten som er aktuell parameter i kallet.

For at dette skal være av interesse, må man kjenne til noen målestørrelser som blir brukt i forbindelse med fonter. Noen av dem er illustrert (med engelske navn) på følgende figur (hentet fra The Java Tutorials):

Det som kalles baseline er en tenkt linje gjennom nederste kant av bokstaver som ikke stikker ned, slik som bokstavene f, r og o. Med descender line menes en tenkt linje gjennom nederste del av bokstaver som stikker ned, slik som g og p. Avstanden mellom baseline og descender line kalles descent. Med ascender line menes en tenkt linje gjennom toppen av bokstaver som stikker opp, slik som b, f og k. Avstanden fra base line til ascender line kalles ascent. Leading er rommet mellom descender line til én linje og ascender line til neste linje. Høyden (height) til en font er avstanden mellom to suksessive base line, som blir det samme som

descent + leading + ascent.

Når vi har fått tak i fontmetrikken, som forklart ovenfor, vil vi ved å gå fram som følger få tak i følgende opplysninger om tekststørrelse:

  int høyde = metrikk.getHeight(); //gir høyden (som definert ovenfor)
  int tekstbredde = metrikk.stringWidth( tekst );
                             //bredden for den tekst som er parameter

Med tekstbredde (engelsk: advance) menes her avstanden mellom punktet lengst til venstre og punktet lengst til høyre på baseline for vedkommende tekst. Merk deg at dette ikke nødvendigvis er det samme som summen av breddene til alle tegnene som teksten inneholder! En gitt tekst kan imidlertid komme til å stikke ut av et rektangel med dimensjonene høyde og tekstbredde som bestemt ovenfor. Men plusser vi på et par piksler i hver retning ved å bruke følgende dimensjon, vil det som regel være tilstrekkelig:

  Dimension tekststørrelse = new Dimension(tekstbredde + 2, høyde + 2);

For øvrig har FontMetrics-klassen get-metoder for både descent, leading og ascent.

Copyright © Kjetil Grønning og Eva Hadler Vihovde, revidert 2014

Forrige avsnitt Neste avsnitt Start på kapittel om grafiske brukergrensesnitt