Kapitel 11. Grafiske brugergrænseflader

Indhold:

Forudsættes af Kapitel 13, Hændelser.

Kapitlet forudsætter Kapitel 10, Appletter og grafik, og at du har adgang til et værktøj, der kan udvikle grafiske brugergrænseflader (f.eks. Borland JBuilder, Oracle JDeveloper, Sun Forte eller IBM VisualAge for Java). Den større opgave forudsætter Kapitel 6, Nedarvning.

Når man skal lave en grafisk brugergrænseflade, gøres det ofte ved at anvende standardkomponenter. Vi vil starte med at se på, hvordan det gøres i praksis med et værktøj.

11.1. Generering med et værktøj

Med moderne udviklingsværktøjer kan man udarbejde en grafisk brugergrænseflade ud fra standardkomponenter på ret kort tid. Herunder er beskrevet, hvordan man gør i Borland JBuilder. JDeveloper har helt de samme muligheder og udseende. Hvis du bruger et andet værktøj, må du prøve dig lidt frem. Ideerne er de samme, og koden, der genereres, ligner også nogenlunde, men menuerne og knapperne varierer selvfølgelig noget.

Figur 11-1. Java

Tag en eksisterende applet, f.eks. MinApplet fra kapitlet om appletter, og føj den til et projekt. Hvis du i stedet vil oprette en ny, så vælg "New.." og Applet. Fjern pakkenavnet, skriv et navn på din klasse, vælg superklasse ("base class") Applet, og klik "Finish". Definér evt. en paint()-metode, der tegner noget (hvis du bruger et andet værktøj end JBuilder, så find menuerne til at oprette en ny applet, og gør det).

  1. Gå over på Design-fanen (ved punkt 1 nederst). Den er delt op i en del, hvor du designer din brugergrænseflade til venstre, og en tabel af egenskaber til højre (punkt 2).

  2. Her skal du først ændre layout fra "<default layout>" til "null" (punkt 2 til højre; måske skal du klikke på den grå flade i designeren først).

  3. Nu kan du gå i gang med at lægge komponenter ind på grænsefladen. Vælg i første omgang at arbejde med AWT-komponenter (punkt 3).

  4. Vælg først en Label (det store A ved punkt 4), og klik på grænsefladen. Der dukker en mærkat med en tekst op. På egenskabstabellen til højre kan du ændre dens variabelnavn (name øverst) til f.eks. labelHvadErDitNavn. Længere nede er egenskaben text, der bestemmer, hvad der skal stå på mærkaten. Ret den til f.eks. "Hvad er dit navn?".

  5. Indsæt derefter et TextField (et indtastningsfelt -punkt 5). Ret variabelnavnet til textFieldNavn og teksten til f.eks. "Jacob".

Gå tilbage til Source-fanen. Nu ser kildeteksten således ud:


import java.awt.*;
import java.applet.*;

public class MinApplet extends Applet
{
  Label labelHvadErDitNavn = new Label();
  TextField textFieldNavn = new TextField();

  public void paint(Graphics g)
  {
    // Herunder referer g til et Graphics-objekt man kan tegne med.
    g.drawLine(10,10,50,70);

    g.fillOval(5,5,300,50);

    g.setColor(Color.green);
    g.drawString("Hej grafiske verden!",100,30);
  }

  public MinApplet() {
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

  private void jbInit() throws Exception {
    labelHvadErDitNavn.setText("Hvad er dit navn?");
    labelHvadErDitNavn.setBounds(new Rectangle(15, 69, 108, 15));
    textFieldNavn.setText("Jacob");
    textFieldNavn.setBounds(new Rectangle(141, 61, 112, 29));
    this.setLayout(null);
    this.add(textFieldNavn, null);
    this.add(labelHvadErDitNavn, null);
  }
}

De to objekter, vi satte på i designeren, er erklæret og oprettet øverst uden for metoderne:


  Label labelHvadErDitNavn = new Label();
  TextField textFieldNavn = new TextField();

Nedenunder står vores gamle paint() uændret. Herunder er der oprettet en konstruktør, der kalder metoden jbInit(). Den andet kode, 'try{ ... } catch (Exception e) {...}', er beregnet til at håndtere undtagelser, og vil blive forklaret senere i Kapitel 14, Undtagelser.

I metoden jbInit() nedenunder lægger JBuilder (og JDeveloper) al sin programkode. Man ser her, hvordan både Label og TextField har metoden setText(), og begge objekter får kaldt denne metode (svarende til, at vi ændrede egenskaben text).


    labelHvadErDitNavn.setText("Hvad er dit navn?");
    textFieldNavn.setText("Jacob");

De andre kommandoer i jbInit() sørger for at placere komponenterne korrekt på appletten.

"Design"- og "Source"-fanen i JBuilder (og JDeveloper) er to måder at se programmet på, og man kan frit skifte mellem dem. Laver man en designændring, vil det blive afspejlet i koden og omvendt. Prøv selv.

11.1.1. Interaktive programmer

Lad os nu tilføje en knap og et indtastningsfelt på flere linjer (TextArea). Jeg kalder dem for buttonOpdater og textAreaHilsen. Knappen skal selvfølgelig gøre noget. Fra Design-fanen, dobbeltklik på knappen, og vupti! Der genereres automatisk en metode til at håndtere et klik:


  void buttonOpdater_actionPerformed(ActionEvent e) {

  }

Hvis du kigger i jbInit(), kan du se, at JBuilder har indsat følgende kode:


    buttonOpdater.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        buttonOpdater_actionPerformed(e);
      }
    });

Det er disse linjer, der sørger for at "lytte efter hændelser" på knappen, sådan at når man klikker på buttonOpdater, så kaldes metoden buttonOpdater_actionPerformed(). Det vil vi komme tilbage til i Kapitel 13, Hændelser.

Nu kan du indsætte kode, der udfører en handling. Skriv f.eks. noget ud til systemoutput:


  void buttonOpdater_actionPerformed(ActionEvent e) {
    System.out.println("Opdater!");
  }

Vi kunne også lave noget sjovere, f.eks. læse den indtastede tekst fra textFieldNavn og skrive den i textAreaHilsen. JBuilder har lavet koden, der sætter teksterne for os, og ved at studere den kan man få en ide til, hvordan det skal gøres:


    String navn = textFieldNavn.getText();     // aflæs navnet

    textAreaHilsen.setText("Hej kære "+navn);  // sæt navnet

Her kommer det fulde eksempel. paint() er ændret til også at tegne navnet 5 gange.


import java.awt.*;
import java.applet.*;
import java.awt.event.*;

public class MinAppletFaerdig extends Applet 
{
  Label labelHvadErDitNavn = new Label();
  TextField textFieldNavn = new TextField();
  Button buttonOpdater = new Button();
  TextArea textAreaHilsen = new TextArea();

  public MinAppletFaerdig() 
  {
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

  public void paint(Graphics g) 
  {
    g.drawLine(10,10,50,70);
    g.fillOval(5,5,300,50);

    g.setColor(Color.green);
    String navn = textFieldNavn.getText();
    for (int i=0; i<50; i=i+10)
      g.drawString("Hej "+navn+" !",100+i,30+i);
  }

  private void jbInit() throws Exception {
    labelHvadErDitNavn.setText("Hvad er dit navn?");
    labelHvadErDitNavn.setBounds(new Rectangle(15, 69, 108, 15));
    textFieldNavn.setText("Jacob");
    textFieldNavn.setBounds(new Rectangle(129, 61, 95, 29));
    buttonOpdater.setLabel("opdater!");
    buttonOpdater.setBounds(new Rectangle(231, 60, 91, 32));
    buttonOpdater.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        buttonOpdater_actionPerformed(e);
      }
    });
    textAreaHilsen.setText("Her kommer en tekst...");
    textAreaHilsen.setBounds(new Rectangle(6, 102, 316, 78));
    this.setLayout(null);
    this.add(labelHvadErDitNavn, null);
    this.add(textAreaHilsen, null);
    this.add(buttonOpdater, null);
    this.add(textFieldNavn, null);
  }

  void buttonOpdater_actionPerformed(ActionEvent e) {
    String navn = textFieldNavn.getText();
    System.out.println("Opdater! navn="+navn);
    textAreaHilsen.setText("Hej kære "+navn);
    repaint(); // gentegn appletten
  }
}

Her har vi tastet "Jacob Nordfalk" ind og trykket på "opdater!"-knappen:

Figur 11-2. Java

Der er altså to måder at arbejde med grafik på:

  • I paint() tegner man "i hånden" ved at give kommandoer til et Graphics-objekt.

  • Ved at bruge grafiske standardkomponenter.