Forrige avsnitt Neste avsnitt Start på kapittel om grafiske brukergrensesnitt

Knapper

Fellesnavnet knapp brukes om følgende typer grafiske komponenter:

KlasseKnappetype
JButtonvanlig knapp
JCheckBoxavkryssingsboks
JRadioButtonradioknapp
JMenuItemmenyalternativ
JCheckBoxMenuItemavkryssingsalternativ i meny
JRadioButtonMenuItemradioknapp i menyalternativ
JToggleButtonav/på-bryter

Når det gjelder den siste typen, JToggleButton, så brukes den vanligvis ikke som den er. Isteden brukes komponenter av en av de to subklassetypene: JCheckBox eller JRadioButton. En JToggleButton ser ut som en vanlig knapp (av type JButton), men virker som en av/på-bryter tilsvarende som en avkryssingsboks.

Alle de nevnte klassene er (direkte eller indirekte) subklasser til AbstractButton. Denne definerer det som er felles for alle typer knapper.

Alle typer knapper kan utstyres med både tekst og bilder, eller bare én av delene. Dessuten kan de knyttes til et tastaturalternativ for aktivering.

Implementasjon av hendelses-håndtering (event-håndtering) for knapper avhenger av hvilken type knapp vi har med å gjøre. Det vanlige er å ha et lytteobjekt av type ActionListener. Dette vil da bli varslet hver gang vi klikker på knappen (eller aktiverer den ved hjelp av tastaturalternativ). For avkryssingsbokser er det imidlertid mer vanlig å bruke et lytteobjekt av type ItemListener. Dette vil da bli varslet hver gang avkryssingsboksen blir valgt eller av-valgt.

Litt om tastaturalternativer

Java skiller mellom tegn og virtuelle tastaturkoder (virtual key codes). Virtuelle tastaturkoder blir indikert med prefikset VK_, slik som i eksemplene VK_A og VK_SHIFT. Virtuelle tastaturkoder svarer til taster på tastaturet. For eksempel vil VK_A svare til tasten med A på tastaturet. Det finnes ingen separate tastaturkoder for små bokstaver, for på tastaturet er det ingen separate taster for små bokstaver.

For å spesifisere tastaturalternativ for en knapp, brukes metoden setMnemonic. Som det vil gå fram av det følgende programeksemplet, kan vi som parameter i denne bruke både et tegn, for eksempel 'h', eller en virtuell tastaturkode, for eksempel VK_H. I begge disse tilfellene ville det ha blitt Alt-H som var tastaturalternativet (det vil si holde Alt-tasten nede mens vi trykker på H-tasten). Dette alternativet ville det også ha blitt om vi hadde brukt 'H' som parameter i setMnemonic-metoden. Hadde vi i dette tilfellet prøvd med tastaturalternativet Alt-shift-H (for å få tegnet H), ville det ikke virket.

Eksempel på bruk av JButton

Vi skal se på et eksempel på bruk av tekst og bilde i en vanlig knapp, av type JButton, hvordan plassering av tekst og bilde innenfor knappen kan styres og hvordan vi kan få bildet til å skifte når musepekeren beveger seg over knappen. Eksemplet er en modifikasjon og utvidelse av eksemplet Fig. 14.15 og Fig. 14.16 i læreboka til Deitel & Deitel, 9. utgave. Den viktigste utvidelsen er at det til knappene er knyttet tastaturalternativer. Vi legger merke til at tastaturalternativene er markert på knappeteksten ved at den bokstaven som gir tastaturalternativet er understreket. Når programmet blir kjørt, vil det gi et vindu som vist på følgende bilde:

Bildene (ikonene) som er brukt på knappene finnes i følgende filer: right.gif, bug1.GIF, bug2.GIF, left.gif. Slik programkoden er skrevet, må disse filene ligge i samme filkatalog som class-fila for vindusklassen. Vinduet er definert i fila Knappevindu.java som er gjengitt nedenfor. Driverklasse for programmet finnes i fila Knappetest.java. Merk deg spesielt koden for å plassere tekst og bilder på knappene, samt koden for å sette tastaturalternativ.

 1 import java.awt.*;
 2 import java.awt.event.*;
 3 import javax.swing.*;
 4
 5 //Bruk av bilde og tekst i knapper
 6 public class Knappevindu extends JFrame
 7 {
 8    private JButton venstreknapp, midtknapp, høyreknapp;
 9
10    public Knappevindu()
11    {
12       super( "Knappedemo" );
13
14       Container c = getContentPane();
15       c.setLayout( new FlowLayout() );
16
17       // oppretter knapper
18       Icon venstreknappikon = new ImageIcon(
19           getClass().getResource("bilder/right.gif" ));
20       venstreknapp = new JButton("Venstre knapp", venstreknappikon);
21       venstreknapp.setVerticalTextPosition( AbstractButton.CENTER );
22       venstreknapp.setHorizontalTextPosition( AbstractButton.LEFT );
23       venstreknapp.setMnemonic( KeyEvent.VK_V );
24       c.add( venstreknapp );
25
26       Icon bug1 = new ImageIcon(
27           getClass().getResource( "bilder/bug1.gif" ));
28       Icon bug2 = new ImageIcon(
29           getClass().getResource( "bilder/bug2.gif" ));
30       midtknapp = new JButton( "Midtknapp", bug1 );
31       midtknapp.setRolloverIcon( bug2 );
32       midtknapp.setVerticalTextPosition( AbstractButton.BOTTOM );
33       midtknapp.setHorizontalTextPosition( AbstractButton.CENTER );
34       midtknapp.setMnemonic( KeyEvent.VK_M );
35       c.add( midtknapp );
36
37       Icon høyreknappikon = new ImageIcon(
38           getClass().getResource("bilder/left.gif" ));
39       høyreknapp = new JButton( "Høyre knapp", høyreknappikon );
40       //bruker default tekstposisjon CENTER, RIGHT.
41       høyreknapp.setMnemonic( 'H' );
42       høyreknapp.setForeground( Color.red );
43       c.add( høyreknapp );
44
45       Knappelytter handler = new Knappelytter();
46       midtknapp.addActionListener( handler );
47       venstreknapp.addActionListener( handler );
48       høyreknapp.addActionListener( handler );
49    }
50
51    private class Knappelytter implements ActionListener
52    {
53       public void actionPerformed( ActionEvent e )
54       {
55          JOptionPane.showMessageDialog( null,
56             "Du klikket på: " + e.getActionCommand() );
57       }
58    }
59 }

Avkryssingsbokser og radioknapper

Både avkryssingsbokser og radioknapper blir brukt til å velge blant alternativer. Forskjellen mellom dem er at avkryssingsbokser blir brukt til å velge ingen, ett eller flere av alternativene i en gruppe av muligheter. Radioknapper blir brukt til å velge nøyaktig ett alternativ. For øvrig har de to typene knapper ulikt utseende.

En avkryssingsboks, type JCheckBox, genererer én ItemEvent og én ActionEvent per klikk i boksen. Vanligvis lytter vi bare på ItemEvent'ene, siden de kan brukes til å avgjøre om det ble avkrysset eller frakrysset (valg opphevet) i avkryssingsboksen.

Radioknapper er en gruppe av knapper som hører sammen og der bare én knapp om gangen kan velges. Knappene oppretter vi som JRadioButton-objekter. Objektene må add'es til et ButtonGroup-objekt. Hver gang brukeren klikker på en radioknapp (selv om den er valgt allerede), blir det generert en ActionEvent. Dessuten vil det bli generert én eller to ItemEvent'er: en fra knappen som nettopp ble valgt, og en fra knappen som ble av-valgt, dersom det var noen.

Det er ButtonGroup-objektet som sørger for at den forrige valgte radioknapp blir av-valgt når en ny blir valgt. En gruppe av radioknapper bør initialiseres slik at én av dem er valgt i utgangspunktet.

Programeksempel med bruk av ItemListener

I programmet Radioknapper.java som det er gjengitt vinduskode for nedenfor, er det et tekstfelt med en demonstrasjonstekst som kan vises i flere forskjellige fonter etter brukerens valg. Navn på valgt font blir skrevet ut i et annet tekstfelt. Når programmet kjøres, kan programvinduet se ut som vist på følgende bilde.

Tre radioknapper brukes til å velge ett av tre mulige fontnavn for teksten. To avkryssingsbokser brukes til å velge fontstil: normal, fet normal, kursiv, eller fet kursiv. Til radioknappene er det brukt lytteobjekt av type ActionListener. (Vi kunne også ha brukt ItemListener.) Til avkryssingsboksene er det brukt lytteobjekt av type ItemListener. Et slikt lytteobjekt må implementere metoden

  public void itemStateChanged( ItemEvent e ) { ... }

I programeksemplet blir det i denne metoden for hver avkryssingsboks sjekket om det er krysset av i den eller ikke. Det får vi gjort ved kall på avkryssingsboksens metode isSelected. Denne returnerer true dersom det er krysset av i boksen, false ellers. På grunnlag av de forskjellige mulige kombinasjonene av avkryssingsalternativer blir det i dette tilfelle valgt stilkode for teksten i tekstfeltet.

Driverklasse for programmet finnes i fila Radioknapptest.java.

 1 import javax.swing.*;
 2 import java.awt.*;
 3 import java.awt.event.*;
 4
 5 //Demonstrasjon av radioknapper og avkrysningsbokser
 6 public class Radioknapper extends JFrame
 7 {
 8   private int stilkode = Font.PLAIN;
 9   private String fontnavn = "Monospaced";
10   private JTextField prøvefelt, infofelt;
11   private JCheckBox fet, kursiv;
12   private ButtonGroup fonter;
13   private JRadioButton mono, dialog, serif;
14                                //skal legges inn i gruppa fonter
15   private Typelytter avkryssingslytter;
16   private Fontlytter radiolytter;
17
18   public Radioknapper()
19   {
20     super( "Radioknapper" );
21     avkryssingslytter = new Typelytter();
22     radiolytter = new Fontlytter();
23     prøvefelt = new JTextField( "Demonstrasjonstekst", 25 );
24     fet = new JCheckBox( "Fet skrift" );
25     fet.addItemListener( avkryssingslytter );
26     kursiv = new JCheckBox();
27     kursiv.setText( "Kursiv" );  //tekst til avkrysningsboks
28     kursiv.addItemListener( avkryssingslytter );
29     fonter = new ButtonGroup();
30     mono = new JRadioButton( "Monospaced", true );
31     mono.addActionListener( radiolytter );
32     dialog = new JRadioButton( "Dialog", false );
33                  //én radioknapp skal være aktivert, resten ikke
34     dialog.addActionListener( radiolytter );
35     serif = new JRadioButton( "Serif", false );
36     serif.addActionListener( radiolytter );
37     fonter.add( mono );
38     fonter.add( dialog );
39     fonter.add( serif );
40     infofelt = new JTextField( 25 );
41     infofelt.setEditable( false );
42     oppdaterFont();
43     Container c = getContentPane();
44     c.setLayout( new FlowLayout() );
45     c.add( prøvefelt );
46     c.add( mono ); //Obs: Radioknappene
47     c.add( dialog ); //adderes til vinduet hver for seg,
48     c.add( serif ); //ikke som en gruppe.
49     c.add( fet );
50     c.add( kursiv );
51     c.add( infofelt );
52     setSize( 300, 160 );
53     setVisible( true );
54   }
55
56   //setter utskriftsfont i samsvar med valg
57   public void oppdaterFont()
58   {
59     Font skrivefont = new Font( fontnavn, stilkode, 16 );
60     prøvefelt.setFont( skrivefont );
61     prøvefelt.repaint();
62     infofelt.setText( "Fontnavn: " + skrivefont.getFontName() );
63   }
64
65   private class Typelytter implements ItemListener
66   {
67     public void itemStateChanged( ItemEvent e )
68     {
69       if ( !fet.isSelected() && !kursiv.isSelected() )
70         stilkode = Font.PLAIN;
71       else if ( fet.isSelected() && !kursiv.isSelected() )
72         stilkode = Font.BOLD;
73       else if ( !fet.isSelected() && kursiv.isSelected() )
74         stilkode = Font.ITALIC;
75       else
76         stilkode = Font.BOLD + Font.ITALIC;
77       oppdaterFont();
78     }
79   }
80
81   private class Fontlytter implements ActionListener
82   {
83     public void actionPerformed( ActionEvent e )
84     {
85       if ( mono.isSelected() ) //eller:  e.getSource() == mono
86         fontnavn = "Monospaced";
87       else if ( dialog.isSelected() ) //eller: e.getSource() == dialog
88         fontnavn = "Dialog";
89       else if ( serif.isSelected() ) //eller: e.getSource() == serif
90         fontnavn = "Serif";
91       oppdaterFont();
92     }
93   }
94 }

De andre typene knapper som er listet opp ovenfor har med menyer å gjøre. Menyer er omtalt i notatet Litt om hvordan man lager menyer.

Copyright © Kjetil Grønning, 2011

Forrige avsnitt Neste avsnitt Start på kapittel om grafiske brukergrensesnitt