Indhold:
Design af en grafisk brugergrænseflade med et udviklingsværktøj
De vigtigste grafiske komponenter og deres egenskaber
Containere og layout-managere
Menuer
Forudsættes af kapitel 13, Hændelser.
Kapitlet forudsætter kapitel 9, Grafiske programmer, 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).
Når man skal lave en grafisk brugergrænseflade (eng.: GUI, graphical user interface), 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.
Med moderne udviklingsværktøjer kan man udarbejde en grafisk brugergrænseflade ud fra standardkomponenter på ret kort tid og uden at skulle programmere ret meget selv.
Herunder er beskrevet, hvordan man gør i Borland JBuilder, med sideløbende forklaringer til udviklingsværktøjerne Oracle JDeveloper og Sun Forte/Netbeans. 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.
I JBuilder/JDeveloper (ikke Forte/Netbeans) er det nemmest at tage en eksisterende klasse, der arver fra Frame eller Applet, f.eks. GrafiskVindue fra kapitel 9.
Hvis du i stedet vil oprette en ny, så vælg 'New..' og Application eller Applet. Fjern pakkenavnet, skriv et navn på din klasse, og klik 'Finish'. Definér evt. en paint()-metode, der tegner noget. I Forte/Netbeans/andre: Opret en ny frame eller applet.
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).
JDeveloper: Højreklik på
GrafiskVindue.java, og vælg 'UI Editor'.
Forte/Netbeans: Gå
over på fanen 'GUI Editing', hvis du ikke allerede står
der.
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).
Forte/Netbeans: Højreklik på den grå
flade, og vælg 'Set Layout' og 'Null layout'.
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).
Vælg først en Label (det store A ved punkt 4), og klik på grænsefladen. Der dukker en etikette 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å etiketten. Ret den til f.eks. "Hvad er dit navn?".
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 nogenlunde således ud:
import java.awt.*; public class GrafiskVindue extends Frame { 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(0,0,50,50); g.fillOval(5,20,300,30); g.setColor(Color.green); g.drawString("Hej grafiske verden!",100,40); } public GrafiskVindue() { 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(). I Forte/Netbeans hedder metoden initComponents().
Den andet kode, 'try{ ... } catch (Exception e) {...}' er beregnet til at håndtere undtagelser og vil blive forklaret i kapitel 14, Undtagelser.
I metoden jbInit() nedenunder lægger værktøjet koden til at initialisere de grafiske komponenter. 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 i vinduet.
"Design"- og "Source"-fanen 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 i jbInit(). Ændrer man i koden, vil designet ændre sig. I Forte/Netbeans er koden beskyttet mod ændringer). Tilføjer du din egen kode til denne metode, så sørg for, at det ligner værktøjets egen kode, ellers kan værktøjet have svært ved at opretholde sammenhængen mellem kode og design.
Lad os nu tilføje en knap og et indtastningsfelt på flere linier (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 (og pakken java.awt.event bliver importeret):
void buttonOpdater_actionPerformed(ActionEvent e) { }
Hvis du kigger i jbInit(), kan du se, at JBuilder har indsat følgende kode:
buttonOpdater.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { buttonOpdater_actionPerformed(e); } });
Det er disse linier, 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 har vi tastet "Jacob Nordfalk" ind og trykket på "opdater!"-knappen (paint() er ændret til også at tegne navnet 5 gange).
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 de grafiske standardkomponenter.
Her kommer det fulde eksempel.
import java.awt.*;
import java.awt.event.*;
public class GrafiskVindue extends Frame
{
Label labelHvadErDitNavn = new Label();
TextField textFieldNavn = new TextField();
Button buttonOpdater = new Button();
TextArea textAreaHilsen = new TextArea();
public void paint(Graphics g)
{
g.drawLine(0,0,50,50);
g.fillOval(5,20,300,30);
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);
}
// Udviklingsværktøj definerer gerne en separat metode hvor de
// initialiserer komponenterne. I JBuilder og JDeveloper hedder
// den jbInit(), mens den hedder initComponents() i Forte/Betbeans.
// Initialiseringen kunne dog lige så godt ligge direkte her i konstruktøren
public GrafiskVindue() {
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
// Udviklingsværktøjets initialisering af komponenter.
// Ændr med varsomhed, ellers kan værktøjet ikke genkende "sin" kode.
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 vinduet
}
}
Grafiske komponenter er objekter, der bruges som en synlig del af en grafisk brugergrænseflade, f.eks. knapper, valglister, indtastningsfelter, etiketter.
Alle komponenter arver fra Component-klassen og har derfor dennes træk til fælles:
Metoderne setForeground(Color c) og setBackground(Color c) sætter hhv. forgrundsfarven og baggrundsfarven for komponenten, svarende til egenskaberne foreground og background. Egenskaberne kan aflæses med getForeground() og getBackground().
En anden egenskab er font, der bestemmer skrifttypen. I tråd med de andre egenskaber sættes den med setFont(Font f) og aflæses med getFont().
Dette kan sammenfattes i en tabel over egenskaber, der er fælles for alle komponenter.
Egenskab |
Type |
Sættes med |
Læses med |
---|---|---|---|
foreground |
Color |
setForeground(Color c) |
getForeground() |
background |
Color |
setBackground(Color c) |
getBackground() |
font |
Font |
setFont(Font f) |
getFont() |
visible |
boolean |
setVisible(boolean synlig) |
isVisible() |
Nedenfor vil de mest almindelige komponenter blive beskrevet. Kun de nye egenskaber er beskrevet.
En
trykknap. Egenskaben label angiver, hvad der står på
knappen.
Egenskab |
Type |
Sættes med |
Læses med |
---|---|---|---|
label |
String |
setLabel(String t) |
getLabel() |
Et
afkrydsningsfelt. Kan både bruges til flueben og til
radioknapper. Hvis man skal have radioknapper (der gensidigt
udelukker hinanden), skal objekterne knyttes sammen af et
CheckboxGroup-objekt.
label angiver, hvad der står ved feltet. state angiver, om feltet er afkrydset.
Egenskab |
Type |
Sættes med |
Læses med |
---|---|---|---|
label |
String |
setLabel(String t) |
getLabel() |
state |
boolean |
setState (boolean afkrydset) |
getState() |
En
valgliste. Brug metoden addItem(String elementnavn) til at tilføje
indgange.
Med getSelectedItem() undersøger man, hvad brugeren har valgt.
Et
indtastningsfelt på en linie. Egenskaben text angiver,
hvad der står i feltet.
Mindre brugt er: columns angiver, hvor bredt feltet skal være.
editable angiver, om brugeren kan redigere teksten i indtastningsfeltet.
echoChar bruges til felter, der skal skjule det indtastede, typisk adgangskoder.
Sæt f.eks. echoChar til '*' for at få vist stjerner i stedet for det indtastede.
Egenskab |
Type |
Sættes med |
Læses med |
---|---|---|---|
text |
String |
setText(String t) |
getText() |
editable |
boolean |
setEditable(boolean rediger) |
isEditable() |
columns |
int |
setColumns(int bredde) |
getColumns() |
echoChar |
char |
setEchoChar(char tegn) |
getEchoChar() |
Et
indtastningsfelt på flere linier.
Egenskaberne text, rows og columns angiver, hvad der står i feltet, hhv. bredde og højde.
Egenskab |
Type |
Sættes med |
Læses med |
---|---|---|---|
text |
String |
setText(String t) |
getText() |
editable |
boolean |
setEditable(boolean rediger) |
isEditable() |
columns |
int |
setColumns(int bredde) |
getColumns() |
rows |
int |
setRows(int højde) |
getRows() |
TextField og TextArea har en del egenskaber til fælles, og disse fællestræk ligger i superklassen TextComponent (se klassediagrammet).
En
etikette, der viser en tekst (som brugeren ikke kan redigere i).
Egenskaben text angiver, hvad der står i feltet.
Egenskab |
Type |
Sættes med |
Læses med |
---|---|---|---|
text |
String |
setText(String t) |
GetText() |
En
menu, hvor flere af indgangene kan ses samtidigt, og hvor man kan
vælge en eller flere elementer. Brug metoden add(String
elementnavn) til at tilføje indgange.
Med isIndexSelected(int index) undersøger man, om en indgang er valgt.
Egenskaberne rows og multipleMode angiver, hvad højden er, og om man kan vælge flere indgange samtidigt.
Egenskab |
Type |
Sættes med |
Læses med |
---|---|---|---|
rows |
int |
setRows(int højde) |
getRows() |
multipleMode |
boolean |
setMultipleMode(boolean m) |
getMultipleMode() |
Et tegne-område. Canvas er en anelse besværlig, idet man skal nedarve fra klassen og implementere paint(Graphics g) for at kunne tegne noget.
En lettere (men ikke nødvendigvis altid smartere) måde er som sagt at definere paint()-metoden direkte i appletten/vinduet, som vi har gjort tidligere.
Herunder et eksempel (genereret med JBuilder), der viser komponenterne omtalt i forrige afsnit.
På billedet ses det resulterende skærmbillede under Windows (sidst i kapitlet ses, hvordan det ser ud under Linux).
public class VisGrafiskeKomponenter { public static void main(String[] arg) { GrafiskeKomponenter vindue = new GrafiskeKomponenter(); vindue.setSize(700,300); vindue.setVisible(true); } }
import java.awt.*; public class GrafiskeKomponenter extends Frame { // opret alle komponenterne og husk dem i nogle objektvariabler Button button1 = new Button(); Checkbox checkbox1 = new Checkbox(); Checkbox checkbox2 = new Checkbox(); Checkbox checkbox3 = new Checkbox(); Checkbox checkbox4 = new Checkbox(); Checkbox checkbox5 = new Checkbox(); CheckboxGroup checkboxGroup1 = new CheckboxGroup(); Choice choice1 = new Choice(); TextField textField1 = new TextField(); TextArea textArea1 = new TextArea(); List list1 = new List(); Label label1 = new Label(); FlowLayout flowLayout1 = new FlowLayout(); // layout-manager (se senere) public GrafiskeKomponenter() { try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } private void jbInit() throws Exception { button1.setLabel("OK"); checkbox1.setLabel("En"); // Sæt afkrydsningsfelternes navne checkbox2.setLabel("To"); checkbox3.setLabel("Tre"); checkbox4.setLabel("Radio1"); // Sæt radioknappernes navne og checkbox5.setLabel("Radio2"); checkbox4.setCheckboxGroup(checkboxGroup1); // gruppen de tilhører checkbox5.setCheckboxGroup(checkboxGroup1); checkboxGroup1.setSelectedCheckbox(checkbox4); choice1.add("Choice Rød"); choice1.add("Choice Grøn"); choice1.add("Choice Blå"); textField1.setColumns(10); textField1.setText("Et TextField"); textArea1.setColumns(15); textArea1.setRows(5); textArea1.setText("Et TextArea"); label1.setText("En Label"); list1.add("List Rød"); list1.add("List Grøn"); list1.add("List Blå"); this.setLayout(flowLayout1);// sæt layout-manager (se senere) this.add(button1, null); // til sidst skal komponenterne føjes this.add(checkbox1, null); // til containeren (se senere) this.add(checkbox2, null); this.add(checkbox3, null); this.add(checkbox4, null); this.add(checkbox5, null); this.add(choice1, null); this.add(textArea1, null); this.add(textField1, null); this.add(label1, null); this.add(list1, null); } }
En container er beregnet til at indeholde komponenter. De arver alle fra Container-klassen og har alle en såkaldt layout-manager tilknyttet, der bestemmer, hvor og med hvilken størrelse komponenterne skal vises i containeren.
Før en komponent bliver vist, skal den tilføjes en container. I eksemplet ovenfor er vinduet den container, komponenterne bliver tilføjet, og derfor står der sidst i initialiseringen:
this.add(button1, null);
Et panel er den simpleste og oftest brugte container. Den indeholder simpelt hen komponenterne (i henhold til layout-manageren).
En applet er et udvidet panel, der er beregnet til at blive vist i en netlæser. Læs kapitel 10, Appletter for mere information om denne klasse.
Window repræsenterer et bart vindue uden en titellinie eller lukkeknap øverst. Det bruges meget sjældent direkte. Man bruger i stedet arvningerne Frame og Dialog.
En Frame er den simpleste og oftest brugte måde at definere et "normalt" vindue med en titel. Læs kapitel 9, Grafiske programmer for mere information om denne klasse.
Dialog bruges til dialog-bokse, vinduer, der dukker op med et eller andet spørgsmål, som skal besvares, før man kan gå videre. Egenskaben modal angiver, om dialog-boksen er modal, dvs. om man skal lukke den, før man kan få adgang til ejer-vinduet. Den sættes med setModal(boolean m) og aflæses med isModal().
Herunder ses klassediagrammet for nogle af komponenterne og containerne.
De hule pile ( ) repræsenterer er-en-relationer (dvs. nedarvning). De andre pile ( ), mellem Container og Component og mellem CheckboxGroup og Checkbox, repræsenterer har-relationer (dvs. at et objekt har en reference til et andet objekt, evt. "ejer" objektet).
Bemærk, at Container selv arver fra Component, så en Container kan i sig selv bruges som en komponent. Det er relevant for Panel og ScrollPane, der er beregnet til at blive placeret inden i andre containere.
En layout-manager styrer layoutet af komponenterne på et Panel eller en anden container. Alle containere har egenskaben layout, der kan sættes med metoden setLayout(Layout l).
I udviklingsfasen er det mest bekvemt at sætte layout-manageren til null, der tillader udvikleren at sætte komponenterne, som han vil på en hvilken som helst (x,y)-position og med en hvilken som helst højde og bredde. Koden ser således ud:
this.setLayout(null); // sæt null-layout this.add(button1, null); // tilføj knap button1.setBounds(new Rectangle(231, 60, 91, 32)); // sæt position/størrelse
null-layout tager slet ikke højde for vinduets størrelse, så hvis vinduet bliver for lille, vil nogle af komponenterne ikke blive vist. Når programmet er ved at være færdigt, bør man derfor ændre programmet til at bruge en layout-manager, der kan styre komponenternes størrelse og indbyrdes placering ud fra deres behov.
FlowLayout placerer komponenterne ligesom bogstaver: Øverst fra venstre mod højre og på en ny linie nedenunder, når der ikke er mere plads.
Angiver man ikke nogen layout-manager i et panel/applet, vil FlowLayout blive brugt.
I eksemplet GrafiskeKomponenter ovenfor blev FlowLayout brugt:
this.setLayout(new FlowLayout()); this.add(button1, null);
BorderLayout tager højde for vinduets størrelse og tilpasser komponenternes størrelse efter den tilgængelige plads. Komponenterne kan placeres på 5 mulige positioner, nemlig NORTH, SOUTH, EAST, WEST og CENTER.
Den mest almindelige måde at lave det grafiske layout af et skærmbillede er med BorderLayout. I de områder, hvor man ønsker at placere flere komponenter, sætter man først et Panel, og komponenterne tilføjes så panelet.
Angiver man ikke nogen layout-manager i et vindue, vil BorderLayout blive brugt (i eksemplet nedenfor kunne de to linier omkring BorderLayout strengt taget fjernes).
import java.awt.*; public class VindueMedBorderLayout extends Frame { Button button1 = new Button(); Button button2 = new Button(); Button button3 = new Button(); Button button4 = new Button(); Button button5 = new Button(); BorderLayout borderLayout1 = new BorderLayout(); public VindueMedBorderLayout() { try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } private void jbInit() throws Exception { button1.setLabel("NORTH"); button2.setLabel("SOUTH"); button3.setLabel("EAST"); button4.setLabel("WEST"); button5.setLabel("CENTER"); this.setLayout(borderLayout1); this.add(button1, BorderLayout.NORTH); this.add(button2, BorderLayout.SOUTH); this.add(button3, BorderLayout.EAST); this.add(button4, BorderLayout.WEST); this.add(button5, BorderLayout.CENTER); } }
Man sætter altså først layoutet ved at kalde setLayout() med et BorderLayout-objekt. Derefter kan add() kaldes med komponenterne og deres placering på borderlayoutet.
Bemærk, at når man bruger en layout-manager, bør man lade den afgøre vinduets størrelse ud fra komponenternes behov, ved at kalde pack() i stedet for setSize() på vinduet. Denne metode pakker komponenterne i vinduet optimalt og sætter vinduesstørrelsen passende.
public class VisVindueMedBorderLayout { public static void main(String[] arg) { VindueMedBorderLayout vindue = new VindueMedBorderLayout(); vindue.pack();// sætter en rimelig vinduesstørrelse (i stedet for setSize()) vindue.setVisible(true); } }
En anden måde at lave layout er med GridBagLayout, som lægger komponenterne efter et usynligt gitter. Hver komponent kan fylde en eller flere celler i højden eller bredden.
import java.awt.*; public class VindueMedGridBagLayout extends Frame { GridBagLayout gridBagLayout1 = new GridBagLayout(); Button knap1 = new Button(); Button knap2 = new Button(); Button knap3 = new Button(); Button knap4 = new Button(); Button knap5 = new Button(); Checkbox chkCe = new Checkbox(); Checkbox chkHø = new Checkbox(); Checkbox chkVe = new Checkbox(); TextArea tekst = new TextArea(); public VindueMedGridBagLayout() { try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } private void jbInit() throws Exception { knap1.setLabel("knap1 (på 3x1 celler)"); knap2.setLabel("knap2 (1x2)"); knap3.setLabel("knap3 (på 1x1 celle)"); knap4.setLabel("knap4 (1x1)"); knap5.setLabel("knap5 (1x1)"); chkHø.setLabel("Højre"); chkVe.setLabel("Venstre"); chkCe.setLabel("Centreret"); tekst.setColumns(15); tekst.setRows(2); tekst.setText("Tekstfelt (3x3 celler)"); this.setLayout(gridBagLayout1); // til sidst skal komponenterne føjes til containeren this.add(knap1, new GridBagConstraints(0, 0, 3, 1, 0.0, 0.0, GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0)); this.add(knap2, new GridBagConstraints(3, 0, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0)); this.add(knap3, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0)); this.add(knap4, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0)); this.add(knap5, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0)); this.add(chkHø, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE,new Insets(0,0,0,0),0,0)); this.add(chkVe, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,new Insets(0,0,0,0),0,0)); this.add(chkCe, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0)); this.add(tekst, new GridBagConstraints(1, 2, 3, 3, 0.0, 0.0, GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0)); } }
Når en komponent tilføjes, angives i et GridBagConstraints-objekt:
Komponentens position (cellekolonne og -række)
Komponentens spændvidde i højde og bredde
Vægt i højde og bredde (komponenter med størst værdi får mest af eventuel overskydende plads)
Justering i tilfælde af overskydende plads (CENTER, EAST, WEST, NORTHEAST, ...)
Om komponenten skal strækkes til at fylde overskydende plads (BOTH, NONE, HORIZONTAL, VERTICAL)
Til sidst nogle parametre til indsættelse af ekstra plads.
Her er koden, der viser vinduet.
public class VisVindueMedGridBagLayout { public static void main(String[] arg) { VindueMedGridBagLayout vindue = new VindueMedGridBagLayout(); vindue.pack(); vindue.setVisible(true); } }
Menuer med rullegardiner er relativt enkle at lave. Herunder ses brudstykkerne af den kode, der skal til for at lave menuerne vist på figuren til højre.
MenuBar menuBar1 = new MenuBar(); Menu menuFil = new Menu(); MenuItem menuItemÅbn = new MenuItem(); MenuItem menuItemAfslut = new MenuItem(); Menu menuHjælp = new Menu(); ... i f.eks jbInit() kunne der stå: this.setMenuBar(menuBar1); menuFil.setLabel("Fil"); menuItemÅbn.setLabel("Åbn"); menuItemAfslut.setLabel("Afslut"); menuFil.add(menuItemÅbn); menuFil.add(menuItemAfslut); menuBar1.add(menuFil); menuHjælp.setLabel("Hjælp"); menuBar1.add(menuHjælp);
For at fange, når brugeren vælger et menupunkt, skal man lytte efter actionPerformed, ligesom med Button-klassen (det blev diskuteret i afsnit 11.1.1).