![]() |
![]() |
Start på kapittel om spesialiserte komponenter for grafiske brukergrensesnitt |
Enkelte vindusprogrammer er implementert på den måten at det innenfor ett, gjerne litt stort hovedvindu kan åpnes flere andre vinduer som tilhører samme programmet. Disse vinduene kan ikke flyttes utenfor hovedvinduet. For eksempel er flere e-post-programmer implementert på denne måten, samt nettlesere.
Alternativet til et slikt opplegg er at man i tillegg til hovedvinduet
bruker dialogvinduer (dialogbokser) som kan plasseres og flyttes fritt i forhold til
hovedvinduet. Slike programmer har vi hatt mange eksempler på. Klassen
JOptionPane
inneholder noen static
-metoder som kan
brukes til å vise noen standardiserte slike dialogvinduer
(for eksempel JOptionPane.showMessageDialog
). Innholdet i
vinduene er det til en viss grad mulig å tilpasse etter egne ønsker.
Større fleksibilitet får vi ved å definere våre egne dialogvinduer, der vi har
like stor frihet i utforming og funksjonalitet som for vinduer ellers.
I notatet
Egenprogrammert dialogvindu er det beskrevet
hvordan du kan gå fram for å få til dette.
Begge de nevnte måtene å organisere et program på har sine fordeler og sine ulemper. Det går dårlig å mikse de to typene; et program bør være enten av den ene eller av den andre typen. Vi skal nå se på hvordan programmer av den første typen, med interne vinduer, kan lages i java.
Interne vinduer definerer vi som subklasser til klassen
JInternalFrame
(som ligger i pakken javax.swing
).
Å opprette GUI for et internt vindu gjør vi på nøyaktig samme måte
som for et vanlig vindu. Som for et slikt, er det også nødvendig
å skrive
setVisible(true)
for at vinduet skal vises på skjermen.
I motsetning til vanlige vinduer, må interne vinduer add'es til en
container, vanligvis av type
JDesktopPane
.
På interne vinduer kan det ikke brukes lytteobjekt av type
WindowListener
. Isteden kan vi bruke typen
InternalFrameListener
. Vanligvis er det imidlertid unødvendig
å implementere et slikt lytteobjekt. Når vi oppretter vindusobjektet for et
internt vindu, kan vi via logiske konstruktørparametre bestemme om det skal
kunne
setSize, pack
eller setBounds
.setLocation
eller setBounds
for å
bestemme plassering.JOptionPane.showInternalXxxDialog(...)
, eller definer
en subklasse til JInternalFrame
. (Bruk ikke
JDialog
.)JDesktopPane
) for å kunne vises. Denne kan settes som
contentPane
for JFrame
-vinduet:
JDesktopPane skrivebord = new JDesktopPane(); setContentPane( skrivebord ); // interne vinduer add'es til skrivebord
setVisible(true)
for å
gjøre interne vinduer synlige.vindu.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
moveToFront
.
Programkode for vindusklassen
Desktoppvindu
er vist nedenfor sammen med klassen Bildepanel
som befinner seg
i samme fil. Programmet er en fornorsket versjon av det som finnes
i Fig. 25.11 i 9. utgave av læreboka til Deitel & Deitel. Det er imidlertid
lagt inn en forflytning av hvert nytt internt vindu, slik at de ikke
blir plassert rett oppå hverandre. Programmets hovedvindu har en meny "Add" med
ett enkelt menyalternativ: "Internt vindu". Hver gang dette velges, blir det
opprettet og vist et nytt internt vindu. Det inneholder et bildepanel definert
av klassen Bildepanel
. Det velges et tilfeldig blomsterbilde blant fem
mulige. Størrelse for hovedvinduet er satt ved bruk av metoden
setBounds
. Denne har fire parametre som angir posisjon for
øverste venstre hjørne, samt bredde og høyde for vinduet.
For øvrig er lukkeknappen for
de interne vinduene programmert til å slette vinduet når det lukkes. Størrelsen til
hovedvinduet settes i forhold til vedkommende skjermstørrelse med et innrykk
på 50 piksler fra hver skjermkant. Skjermstørrelsen får vi tak i ved
instruksjonen
31 Dimension skjermstørrelse =
32 Toolkit.getDefaultToolkit().getScreenSize();
Programmet gjør bruk av bildefilene
yellowflowers.png,
purpleflowers.png,
redflowers.png,
redflowers2.png,
lavenderflowers.png.
Disse må ligge i en underkatalog "bilder" i forhold til programmets class-filer. Driverklasse
for programmet finnes i fila
Desktopptest.java
.
Følgende bilde
viser programvinduet etter at det er opprettet fem interne vinduer.
1 import java.awt.*; 2 import java.awt.event.*; 3 import javax.swing.*; 4 5 public class Desktoppvindu extends JFrame 6 { 7 private JDesktopPane desktopp; 8 private int vindusteller = 0; //antall åpnede indre vinduer 9 private int xForflytning = 30, yForflytning = 30; //brukes i lytter 10 //for å få nye indre vinduer forskjøvet i forhold til hverandre 11 12 public Desktoppvindu() 13 { 14 super("Bruk av JDesktopPane og interne vinduer"); 15 16 // oppretter meny 17 JMenuBar menylinje = new JMenuBar(); 18 JMenu addmeny = new JMenu("Add"); 19 JMenuItem lagInternvindu = new JMenuItem("Internt vindu"); 20 lagInternvindu.addActionListener(new Menylytter()); 21 addmeny.add(lagInternvindu); 22 menylinje.add(addmeny); 23 setJMenuBar(menylinje); 24 25 // oppretter desktoppen som skal inneholde de interne vinduene 26 desktopp = new JDesktopPane(); 27 getContentPane().add(desktopp, BorderLayout.CENTER); 28 29 //Lar det store vinduet bli indentert 50 pixler fra hver skjermkant: 30 int innrykk = 50; 31 Dimension skjermstørrelse = 32 Toolkit.getDefaultToolkit().getScreenSize(); 33 setBounds(innrykk, innrykk, skjermstørrelse.width - innrykk * 2, 34 skjermstørrelse.height - innrykk * 2); 35 setVisible(true); 36 } // slutt på konstruktør 37 38 private class Menylytter implements ActionListener 39 { 40 // oppretter og viser et nytt internt vindu 41 public void actionPerformed(ActionEvent event) 42 { 43 JInternalFrame internvindu = new JInternalFrame( 44 "Internt vindu #" + (++vindusteller), 45 true, //kan endre størrelse 46 true, //kan lukkes 47 true, //kan maksimeres 48 true); //kan ikonifiseres 49 50 // plasserer et panel i det nye interne vinduet 51 Container container = internvindu.getContentPane(); 52 Bildepanel panel = new Bildepanel(); 53 container.add(panel, BorderLayout.CENTER); 54 55 // velger å la vinduet bli slettet når det lukkes (default er 56 // HIDE_ON_CLOSE, dvs. at det skjules, men ikke slettes 57 internvindu.setDefaultCloseOperation( 58 JInternalFrame.DISPOSE_ON_CLOSE); 59 60 // gjør det interne vinduet akkurat stort nok til å romme det 61 // bildepanelet som det inneholder 62 internvindu.pack(); 63 64 //sørger for at det interne vinduet ikke kommer rett 65 //oppå et annet vindu 66 internvindu.setLocation(xForflytning * (vindusteller - 1), 67 yForflytning * (vindusteller - 1)); 68 69 // plasserer det interne vinduet på desktoppen og viser det 70 desktopp.add(internvindu); 71 internvindu.setVisible(true); 72 } 73 } // slutt på klasse Menylytter 74 } // slutt på klasse Desktoppvindu 75 76 // Definerer et panel for visning av et bilde. 77 class Bildepanel extends JPanel 78 { 79 80 private ImageIcon bilde; 81 private String[] bildefiler = 82 { 83 "yellowflowers.png", "purpleflowers.png", 84 "redflowers.png", "redflowers2.png", "lavenderflowers.png" 85 }; 86 87 // velger et tilfeldig bilde for panelet 88 public Bildepanel() 89 { 90 int randomNumber = (int) (Math.random() * 5); 91 bilde = new ImageIcon(getClass().getResource( 92 "bilder/" + bildefiler[randomNumber])); 93 } 94 95 // tegner ut bildet på panelet 96 public void paintComponent(Graphics g) 97 { 98 super.paintComponent(g); 99 bilde.paintIcon(this, g, 0, 0); 100 } 101 102 // returnerer bildets størrelse 103 public Dimension getPreferredSize() 104 { 105 return new Dimension(bilde.getIconWidth(), 106 bilde.getIconHeight()); 107 } 108 } // slutt på klasse Bildepanel
Copyright © Kjetil Grønning og Eva Hadler Vihovde, revidert 2014
![]() |
![]() |
Start på kapittel om spesialiserte komponenter for grafiske brukergrensesnitt |