Forrige avsnitt Neste avsnitt  Start på kapittel om spesialiserte komponenter for grafiske brukergrensesnitt

Litt om bruk av interne vinduer (Internal Frames)

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.

Likheter og forskjeller mellom vinduer og interne vinduer

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

Regler for å bruke interne vinduer

Programeksempel

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

Forrige avsnitt Neste avsnitt  Start på kapittel om spesialiserte komponenter for grafiske brukergrensesnitt