JFrame, JWindow, JApplet och lite till

Det finns en bra artikel hos SUN som behandlar containers, du hittar den på http://java.sun.com/products/jfc/tsc/articles/containers/. Alla GUI måste ha en tungviktare i botten, dvs JApplet, JFrame, JDialog eller JWindow.

JPanel

JPanel är en lättviktare som ärver av JComponent. Den används främst för att gruppera komponenter när ett fönsters layout skapas. Den tillför ingen ytterligare funktionalitet till JComponent.

JRootPane

I motsats till AWT ska layouthanterare inte sättas och inga komponenter placeras direkt i en JFrame, JWindow, JDialog eller JApplet. Alla dessa fyra fylls helt av ett objekt av klassen JRootPane. Inte heller i JRootPane ska några komponenter placeras eller layouthanterare ändras. En JRootPane har sin egen layouthanterare, RootLayout, som behärskar dess speciella funktion.

JRootPane innehåller en glassPane och en layeredPane. Den senare innehåller i sin tur en contentPane och en menuBar, se bilden nedan.

Vad ska då alla dessa användas till? Vill du inte tillföra någon ny funktionalitet till ditt fönster kan du hantera contentPane precis som du skulle hantera till exempel en Frame i AWT, sätta layouthanterare, lägga till komponenter osv. Det enda du behöver tänka på är att verkligen jobba med contentPane och inte något av de andra objekten. Du får tag i contentPane genom att anropa metoden getContentPane(). Här kommer ett exempel, SimpleFrame.java. För att inte göra ditt fönster onödigt krångligt är det bra att komma ihåg att contentPane default är ett objekt av JPanel. Det finns alltså ingen anledning att placera en (till) JPanel i den. Det går också bra att byta ut den mot ett annat objekt, vill du ha till exempel en JScrollPane i din frame ska du inte lägga den i contentPane utan istället byta ut framens contentPane. Det görs genom att anropa metoden setContentPane().

JMenuBar är en vanlig menyrad. Den är defalut satt till null, dvs det finns ingen plats för menyer. Mer om detta längre fram när vi avhandlar menyer.

Nu återstår det roliga, glassPane och layeredPane. Vi börjar med glassPane. Den ligger alltid överst och täcker hela fönstret, i den kan du alltså lägga sådant som du vill ha framför alla andra komponenter. Här är ett exempel, GlassExample.java, som blockerar framen för mushändelser, till exempel att klicka på en knapp. GlassPane registreras som lyssnare av mushändelser, vilka därför inte når contentPane då de bara skickas till översta registrerade lyssnare. När knappen "Start" trycks ner blir glassPane osynlig och det går att klicka på knapparna i contentPane. Observera att glassPane är genomskinlig. Default är glassPane ett objekt av klassen JPanel, men det går bra att byta ut den mot någon annan Component.

Slutligen finns layeredPane. Den är av klassen JLayeredPane (och bör så förbli), vilken kan placera komponenter i olika lager. Det går att använda "obegränsat" antal lager. Ett lager anges som ett Integer-objekt. Lager med högre tal placeras ovanpå lager med lägre tal. Observera att JLayeredPane inte har någon layouthanterare. Det innebär att om du ska placera fler komponenter i samma lager bör de placeras i en Container (med layouthanterare) som sedan placeras i önskat lager. Nu ett exempel, SimpleLayers.java, som placerar ut tre knappar (utan text) ovanpå varandra. Mer meningsfulla blir lagren om man utgår från de konstanter som JLayeredPane definierar, se nedan. Med början nedifrån finns följande sex Integer-konstanter som är avsedda för att representera lager.


JFrame

Ärver inte av JComponent, utan av java.awt.Frame. Förutom vad som angetts under JRootPane ovan är den mycket lik sin superklass. En nyhet är en property vid namn defaultCloseOperation, vilken anger vad som ska ske vid windowClosing om inget annat angetts. Möjliga värden är de fyra konstanterna EXIT_ON_CLOSE, DISPOSE_ON_CLOSE, HIDE_ON_CLOSE (default) och DO_NOTHING_ON_CLOSE. De tre sista hittas i interfacet WindowConstants, EXIT_ON_CLOSE finns i JFrame. Se detta exempel, FrameClose.java. JRootPane har en metod setDefaultButton(JButton b), den knapp som skickas dit blir den som skickar ActionEvent om användaren klickar på enter medans framen som root panen ligger i har fokus.

JWindow

Ärver inte av JComponent, utan av java.awt.Window. Förutom vad som angetts under JRootPane ovan är den helt lik sin superklass. Ett JWindow är ett fönster som bara utgörs av en yta, dvs det har inte kanter, titel, eller menyer som en frame. En avändning är för att göra en splash screen, dvs en sådan ruta med reklam och annan nyttig information som visas när ett program startar.

JApplet

Ärver inte av JComponent, utan av java.awt.Applet. Förutom vad som angetts under JRootPane ovan (och att den därmed kan ha menyer) är den mycket lik sin superklass. Om du kompilerar om en applet får du inte in den nya class-filen med mindre än att starta om browsern. Att trycka på reload hjälper inte.

Om du får ett meddelande om att appleten försökt komma åt system event queue men inte fått tillstånd till det kan du lägga till raden getRootPane().putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE); Felmeddelandet ska då att försvinna (jag har inte testat det).

Kom ihåg vad som nämnts om trådar i Swing. När metoden init() är klar är det mycket oklokt att påverka bildskärmen från någon annan tråd än event-dispatch thread.