Komponenten JPanel
har inget eget innehåll men kan användas bl.a. till att fylla med andra komponenter. Man kan ställa in en layoutmodell för JPanel
som skiljer sig från huvudfönstrets. Med JPanel
kan man skapa en hierarki av grafiska element där olika delar är organiserade enligt olika layoutmodeller.
En JCheckBox
är en kryssruta som antingen kan vara vald eller inte. Metoden isSelected()
används för att avgöra dess status.
JTextField
är en komponent för inmatning av enradig text. En ActionListener
till en sådan komponent anropas då användaren har tryckt på enter. getText()
ger aktuellt innehåll i rutan.
Genom att ärva existerade komponenter kan man modifiera dem, t.ex. förändra utseendet.
Vill man rita grafik, t.ex. diagram eller bilder så är det bra att utgå från JPanel
eftersom man vill bestämma innehållet helt själv.
Alla komponenter har en metod som ritar innehållet varje gång detta behövs, paintComponent
. Denna tar som argument ett objekt av typen Graphics
som är en miljö för komponentens yta som tillåter grafiska operationer.
Man överlagrar (definierar en ny) uppritningsmetod
@Override
public void paintComponent(Graphics g) {
...
}
@Override
är inte nödvändigt men rekommenderat för att göra det tydligt att man ersätter en metod i någon superklass. Mer om detta vid ett annat tillfälle.
I Graphics
finns metoder för att rita linjer (drawLine
), cirklar och andra figurer, bilder och text.
Om lyssnare till händelser ändrar på något som gör att en egen komponent behöver ritas om så anropar man repaint()
. Man ska aldrig direkt anropa paintComponent
. Detta görs av Swings egen loop som hanterar händelser, lyssnare och omritning av komponenter.
Om man vill hantera input från mus använder man en speciell lyssnare, MouseListener
, och händelser, MouseEvent
. En lyssnare kopplas till den komponent som ska hantera mushändelser. Positionen för musen anges relativt denna komponent. Detta är ett gränssnitt med många metoder för olika typer av händelser; mouseClicked
, mouseMover
etc. Är man bara intresserad av att hantera några få typer så kan man för bekvämlighets skull utgår från motsvarande adapter, MouseAdapter
. Där har alla metoder getts en tom implementation och man behöver bara överskugga dem man vill använda.
För tangentbordshändelser finns på motsvarande sätt interfacet KeyListener
och KeyEvent
.
Ibland, t.ex. i spel, vill man att saker ska förändras bara av att tiden går, inte att användaren ger något input. För program som använder Swing kan man använda klassen Timer
. Den har en konstruktor som tar en heltal som anger i millisekunder hur ofta den ska generera en händelse och en ActionListener
som anropas.
Till en JFrame
kan man koppla en JMenuBar
med metoden setJMenuBar
. Till en JMenuBar
kan man addera flera JMenu
. Till en JMenu
kan man addera flera JMenuItem
.
Det går att skapa undermenyer, kortkommandon som automatiskt visas, ikoner, checkbox-alternativ i menyer och det mesta annat man ser i applikationer.
Ofta finns det flera sätt i GUIt att utföra ett visst kommando, t.ex. både en knapp och i menyerna. Det finns ett koncept Action
som abstraherar ett kommando bort från hur användaren startat det. Samma Action
kan startas på flera olika sätt. Action
är ett interface som, liksom MouseListener
, innehåller många metoder medan man ofta bara vill implementera en. Liksom MouseAdapter
finns AbstractAction
, en klass som låter definiera bara det nödvändiga.
För att säga ett en komponent, Button
eller MenuItem
, ska utföra en viss Action
, använd metoden setAction
. Knappar och menyalternativ som har en Action
satt tar sin titel från denna, så tänk på att ställa in titeln på Action
. Det finns en konstruerare för detta i AbstractAction
.
Det finns några klasser och metoder i Swing för att enkelt visa dialogfönster, t.ex.:
JFileChooser
– filväljardialogJOptionPane.showMessageDialog
– visa meddelande i liten rutaMan kan också bygga egna dialogfönster genom att utgå från klassen JDialog
.
Sättet att implementera interaktionen i ett GUI med händelser och lyssnare är besläktat med ett designmönster (design pattern) för OOP, nämligen Observer. Den går ut på att objekt kan ha två roller, Observable eller Observer. Observable-objekt representerar värden vars förändringar är intressant för Observer-objekt. Därför har Observable-objekt en lista med Observer-objekt. I denna lista kan objekt som vill veta när något ändras i Observable-objektets värde/tillstånd registrera sig. När Observable-objektet ändrar sitt tillstånd så anropas en metod i de registrerade Observer-objekten som hanterar förändringen.
Detta kan man implementera enkelt genom ett interface för Observer som specificerar en metod som ska anropas vid förändring, på samma sätt som t.ex. ActionEventListener
som vi sett tidigare. Varje klass som ska vara Observable tillhandahåller metoder för att lägga till sig till och ta bort sig från listan av Observers.
Ett exempel på designmönstret Observer är en mekanism som finns implementerad i de olika komponentklasserna i Swing. De egenskaper objekt av dessa klasser har, t.ex. bakgrundsfärgen, har enhetliga setters och getters, setBackground
, getBackground
.
Men man kan också i andra objekt få reda på när någon egenskap har förändrats. Detta genom att klassen som vill ha informationen implementerar PropertyChangeListener
som har en metod propertyChange
. Alla komponentklasser har metoder för att registrera och avregistrera lyssnare/observers som implementerar detta interface. De metoderna heter addPropertyChangeListener
och removePropertyChangeListener
.
När någon egenskap i komponent-objekt förändras så skapas en PropertyChangeEvent
och alla lyssnare/observers anropas. En PropertyChangeEvent
innehåller information om namnet på egenskapen som förändrats, samt egenskapens gamla och nya värde.