Swing
Lisaks kümnekonnale paketis java.awt asuvale komponendile saab
kasutajaga suhtlemiseks kasutada ka paketi javax.swing graafilisi
komponente. Nagu eelpool graafikakomponentide peatükis kirjeldatud,
palutakse awt-komponendid joonistada operatsioonisüsteemil, swing-komponente
joonistatakse Java vahenditega. Sellest tulenevalt näevad esimesed välja nii
nagu vastavas operatsioonsiüsteemis tavaks, swingi nupp või silt aga on igal
pool tavajuhul peaaegu ühesugune. UIManageri abil aga on võimalik panna ka
swing-komponente vastavalt operatsioonisüsteemile välja nägema.
Swingi graafikakomponendid algavad tähega J. Tõenäoliselt seetõttu,
et neid oleks kerge eristada analoogilistest awt komponentidest. Järgnevas
näiteks on raamiks JFrame, selle sees on silt JLabel ning nupp JButton. Nii
nupule kui sildile (ja ka mitmetele muudele komponentidele) saab tema
ilmestamiseks määrata ikooni. ImageIcon loob ikooni kasutades aluseks
pildifaili, kuid vajadusel saab ikooni ka käskude abil joonistada. Kõikidele
swingi komponentidele saab määrata ToolTipText'i. Seda näidatakse ekraanile
juhul, kui kasutaja on hiirega vastava komponendi peale liikunud. Enamasti
vastav tekst seletab komponendi otstarvet või annab kasutajale
tegutsemissoovitusi. Korraldus setMnemonic lubab klahvikombinatsiooni (Alt +
täht) võrdsustada hiirega nupule vajutamisele.
Komponentide raami lisamisel tuleb swingi puhul määrata, millisesse
kihti ta paigutada. Harilikult kasutatava alumise kihi saab kätte
getContentPane() abil. Pealmist kihti nimetatakse GlassPane ning
vahepealsetesse kihtidesse paigutamiseks saab kasutada LayeredPane
vahendeid. Kihtidega mängides saab komponente mitmesse kihti paigutada.
import java.awt.*;
import javax.swing.*;
public class Pildid{
public static void main(String argumendid[]){
JLabel silt=new JLabel("Maja silt");
Font suurkiri=new Font("Serif", Font.BOLD+Font.ITALIC, 30);
Icon majapilt=new ImageIcon("maja.gif");
silt.setFont(suurkiri);
silt.setIcon(majapilt);
JButton nupp=new JButton("Maja nupp", majapilt);
nupp.setToolTipText("Head vajutamist!");
nupp.setMnemonic(java.awt.event.KeyEvent.VK_M);
JFrame f=new JFrame("Sildiraam");
Container p=f.getContentPane();
p.setLayout(new GridLayout(2, 1));
p.add(silt);
p.add(nupp);
f.pack();
f.setVisible(true);
}
}
HTML-kujundus
Swingi komponentidel näidatavat teksti saab HTMLi abil kujundada.
Täpne väljanägemine võib sõltuda intepretaatorist, kuid selliselt on
programmi väljanägemist lihtsam pilkupüüdvaks muuta kui awt vahenditega
kujundades. Nagu lihtsat teksti kandva sildi puhul, nii ka siin on võimalik
programmi töö käigus sildi sisu muuta.
import javax.swing.*;
public class HtmlLabel{
public static void main(String argumendid[]){
JFrame f=new JFrame("Kujundatud silt");
JLabel silt=new JLabel(
"
Pealkirja
\n"+
"ja punase tekstiga silt"
);
f.getContentPane().add(silt);
f.pack();
f.setVisible(true);
}
}
Sisemised raamid
Mõnes programmis on näha, et pearaami sees on omaette väiksemad
raamid. Nii näiteks Wordi puhul võib iga tekst olla lahti omaette raamis,
need aga omakorda suure Wordi raami sees. Sellist olukorda Java keskkonnas
saab tekitada JInternalFrame abil. Nemad käituvad JDesktopPane sees samuti
nagu harilikud raamid suure ekraani sees. Tema sees paiknevasse paneeli saab
lisada komponente nagu ikka. Ka sisemisi raame saab muuta ikooniks alla
serva, suurendada ja vähendada. Kui suure raami teateid püüab
WindowListener, siis siseraamiga toimuva teada saamiseks aitab
InternalFrameListener. Vorm on küll erinev, kuid võimalused samad.
import javax.swing.*;
public class SiseraamigaRaam{
public static void main(String argumendid[]) throws Exception{
JInternalFrame siseraam1=new JInternalFrame("Esimene");
JInternalFrame siseraam2=new JInternalFrame("Teine",
true, true, true, true);
siseraam2.getContentPane().add(new JTextArea());
JDesktopPane paneel=new JDesktopPane();
siseraam1.setSize(200, 100);
siseraam1.setLocation(10, 80);
siseraam1.setVisible(true);
paneel.add(siseraam1);
siseraam1.setSelected(true);
siseraam2.setVisible(true);
paneel.add(siseraam2);
siseraam2.setSize(150, 150);
siseraam2.setLocation(120, 50);
JFrame f=new JFrame("Kest");
f.setContentPane(paneel);
f.setSize(300, 300);
f.setVisible(true);
}
}
Värvivalija
Kasutajapoolseks värvi valimiseks saab vajadusel kirjutada ise
dialoogiakna, kust hiirega omale sobiv värv leida võimalik on. Swingi all
aga on programmeerimisvaeva vähendamiseks loodud komponent JColorChooser,
mille abil kasutaja saab pakutavate hulgast sobiva värvi välja valida.
Värvivalikuks pakub komponent kolme võimalust: esimesel juhul saab hiirega
vajutada sobivat värvi ruudule. Teisel puhul saab valida värvi ning teiselt
skaalalt värvile vastava tumeduse. Kolmandas valikuaknas lastakse kasutajal
määrata punase, rohelise ning sinise vahekord loodavas värvis. Vaikimisi
kujul näitab komponent otsitavat värvi mitmesuguste kujundite ning
ingliskeelse teksti peal. Selle kujundi saab aga vajadusel programmi ilmele
sobivama või hoopis tühja pisikese paneeli vastu välja vahetada (järgnevas
näites vastav rida välja kommenteeritud). Värvivaliku registreerimiseks ning
temale reageerimiseks saab kasutada kuularit. Värvivaliku klassi juurde on
loodud meetodid ka dialoogiakna kaudu värvi valimiseks.
import javax.swing.*;
import javax.swing.event.*;
public class Varvivalik{
public static void main(String argumendid[]){
final JTextArea tekstiala=new JTextArea("Värvilised tervitused");
final JColorChooser valija=new JColorChooser();
// valija.setPreviewPanel(new JPanel());
valija.getSelectionModel().addChangeListener(
new ChangeListener(){
public void stateChanged(ChangeEvent e){
tekstiala.setForeground(valija.getColor());
}
}
);
JFrame f=new JFrame("Värvivalik");
java.awt.Container p=f.getContentPane();
p.add("Center", tekstiala);
p.add("South", valija);
f.setSize(300, 500);
f.setVisible(true);
}
}
Failinime valija
Ka failinime failinime valimise dialoogi saab ise suurema vaevata
kirjutada, kuid swingi klass JFileChooser on juba vastavaks otstarbeks
loodud ilusasti kujundatud komponent. Saab määrata, millisest kataloogist
alates faili otsima saab hakata. Meetod showOpenDialog avab dialoogi ning
programm jääb kasutajapoolset valikut ootama. Kui fail on valitud või
valimine tühistatud, läheb programm edasi ning komponendi meetodite kaudu
saab teada kasutaja vastuse. Kui soovitud fail on käes, saab temaga samuti
toimida nagu failiga ikka, s.t. tema kohta infot küsida, sealt lugeda või
sinna kirjutada.
import javax.swing.*;
import java.io.*;
public class Failivalik{
public static void main(String argumendid[]){
JFileChooser valija=new JFileChooser(new File("."));
valija.showOpenDialog(new JFrame());
System.out.println("Valiti "+valija.getSelectedFile());
}
}
Failivalikut saab veidi programmiga kohandada. Näiteks võib määrata
avamisnupu peal olevat kirja. Samuti võib lubada korraga mitut faili valida.
Järgnevas näites lisatakse filtri abil võimalus eraldi vaid pildifailide
hulgast kasutajal sobivat otsida. Filtri loomisel tuleb üle katta meetodid
accept ning getDescription. Esimesele antakse järjekorras ette kõik failid,
mida parasjagu oleks võimalik valida. See meetod peab igaühe kohta neist
ütlema, kas vastavat faili kasutajale näidata või mitte. Meetod
getDescription väljastab filtrile sobivate failide ühisnimetaja, siin näites
"Pildifailid".
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
public class Failivalik2{
public static void main(String argumendid[]){
JFileChooser valija=new JFileChooser(new File("."));
valija.addChoosableFileFilter(new Pildifilter());
valija.showDialog(new JFrame(), "Vali fail");
System.out.println("Valiti "+valija.getSelectedFile());
}
}
class Pildifilter extends FileFilter{
public boolean accept(File f){
String failinimi=f.getName();
if(failinimi.endsWith(".gif")|failinimi.endsWith(".jpg"))
return true;
else return false;
}
public String getDescription(){
return "Pildifailid ";
}
}
Puud
Infohulgas orienteerumiseks saab andmeid esitada puuna. Siis on
kasutajal võimalik ekraanilt kasutu kõrvaldada ning hierarhia abil enesele
sobiv üles leida. Puu abil on näiteks esitatud failid ja kataloogid
FileManageris ja WindowsExploreris. Puusse saab lisada kõiki objekte.
Vaikimisi juhul määrab JTree ise okstele ja lehtedele sobivad ikoonid ning
objekti kirjelduseks kasutab sõnet mille väljastab ta toString meetod.
Vajadusel aga saab nii ikooni kui kirjeldust muuta.
Puu hierarhia saab kokku panna DefaultMutableTreeNode abil. Kui ta
on reas viimane, on ta leht, keskel oks ning algul juur. Puu ekraanile
kuvamiseks tuleb luua JTree, kellele määrata juur, millest alates elemente
näidata tuleb. Siin näites on pandud juureks ülikool, tema alla paar
teaduskonda ning teaduskonna alla mõni õppetool. Võib jääda mulje, nagu
tuleks puu loomiseks hirmus palju kirjutada, kuid suuremate andmehulkade
korral saab luua või kasutada olemasolevaid alamprogramme ning puu tegemine
polegi kuigi keeruline.
import javax.swing.*;
import javax.swing.tree.*;
public class Puu{
public static void main(String argumendid[]){
DefaultMutableTreeNode juur=new DefaultMutableTreeNode("Ülikool");
DefaultMutableTreeNode teaduskond=new DefaultMutableTreeNode(
"Matemaatika-Loodusteaduskond");
teaduskond.add(new DefaultMutableTreeNode("Informaatika õppetool"));
teaduskond.add(new DefaultMutableTreeNode("Bioloogia õppetool"));
juur.add(teaduskond);
juur.add(new DefaultMutableTreeNode("Kultuuriteaduskond"));
JTree puu=new JTree(juur);
JFrame f=new JFrame("Puu");
f.getContentPane().add(puu);
f.setSize(200, 200);
f.setVisible(true);
}
}
Kasutaja tegevuse registreerimiseks saab tarvitada mitmesuguseid
kuulareid. Saab teada, millal ta puu nähtavat osa suurendas või vähendas,
mis osa puust nähtav on, millal mõni element valiti. Ka pärast puu loomist
saab temasse elemente lisada ja sealt eemaldada. Käsklus
puu.putClientProperty("JTree.lineStyle", "Angled"); palub puu osad omavahel
joontega ühendada. Siin näites trükitakse igal valikul välja valitud
komponent. TreeSelectionEvent'i meetod getPath() annab tulemuseks kogu rea
alates juurest kuni märgitud leheni. Selle kaudu oleks võimalik ükskõik
millise tee peale jääva komponendi poole pöörduda. Meetod
getLastPathComponent() annab tulemuseks tee viimase elemendi, ehk selle,
millele kasutaja vajutas.
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class Puu2a{
public static void main(String argumendid[]){
DefaultMutableTreeNode juur=new DefaultMutableTreeNode("Ülikool");
DefaultMutableTreeNode teaduskond=new DefaultMutableTreeNode(
"Matemaatika-Loodusteaduskond");
teaduskond.add(new DefaultMutableTreeNode("Informaatika õppetool"));
teaduskond.add(new DefaultMutableTreeNode("Bioloogia õppetool"));
juur.add(teaduskond);
juur.add(new DefaultMutableTreeNode("Kultuuriteaduskond"));
JTree puu=new JTree(juur);
puu.addTreeSelectionListener(
new PuuKuular()
);
puu.putClientProperty("JTree.lineStyle", "Angled");
JFrame f=new JFrame("Puu");
f.getContentPane().add(puu);
f.setSize(200, 200);
f.setVisible(true);
}
}
class PuuKuular implements TreeSelectionListener{
public void valueChanged(TreeSelectionEvent e){
System.out.println(e.getPath().getLastPathComponent());
}
}
Paigutus
JSplitPane võimaldab temale eraldatud pinna jaotada kahe komponendi
vahel. Tuleb vaid määrata, kas pind jaotatakse kaheks horisontaalselt või
vertikaalselt ning komponendid, mis kummasegi ossa panna. Lisameetoditega
saab määrata ja muuta jagamise kohta, samuti kasutajapoolset vahepiiri
nihutamise võimalusi. Jagatud paneelidena näevad välja mitut lehte
sisaldavad brauseri aknad, kus vasakul näiteks sisukord ja paremal sisu.
import javax.swing.*;
public class Jaotuspaneel{
public static void main(String argumendid[]){
JSplitPane paneel=new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
new JButton("Ülemine"),
new JToggleButton("Alumine")
);
JFrame f=new JFrame("Jagatud raam");
f.getContentPane().add(paneel);
f.setSize(200, 200);
f.setVisible(true);
}
}
Kui määranguaknas on võimalusi rohkem kui kasutajale korraga
mõistlik näidata on, siis JTabbedPane abil saab muud paneelid ülekuti
paigutada. Sarnaselt on loodud näiteks Exceli lahtrimäärangute dialoogiaken,
kus ühel paneelil saab määrata andmete tüüpi, teisel kujundust jne. Soovi
korral saab paneelivaliku nuppudele lisada ikoonid, eemaldada, vahetada ja
lisada paneele, mõne valiku tegemist keelata, automaatselt soovitud paneel
esile tuua ning mitmel moel kasutaja tegevuse kohta teateid saada.
import javax.swing.*;
public class Valikupaneel{
public static void main(String argumendid[]){
JPanel p1=new JPanel(new java.awt.GridLayout(2,1));
p1.add(new JButton("Ülemine"));
p1.add(new JButton("Alumine"));
JTabbedPane paneel=new JTabbedPane();
paneel.add("Esimene", p1);
paneel.add("Teine", new JLabel("Suur silt"));
JFrame f=new JFrame("Valikupaneeli näide");
f.getContentPane().add(paneel);
f.setSize(200, 200);
f.setVisible(true);
}
}
Swingi kokkuvõte
Swingi paketis on hulk klasse, mis peaksid aitama kasutajal
programmiga meeldivalt suhelda. Samuti on püütud nende loomisel silmas
pidada erivahendite kasutajaid (ekraanilt lugejad, lihtsustatud
klaviatuurid). Lisaks eelnevalt kommenteeritutele kuuluvad siia paketti veel
mitmed sageli kasutust leidvad komponendid: JMenuBar, JMenu, JSeparator,
JMenuItem, JCheckBoxMenuItem ja JPopupMenu menüüde loomiseks; JToolBar
tööriistariba tarvis. Action-liidese abil saab samastada menüüelemendi ning
tööriistariba nupu. Tabelisse paigutada aitab JTable ning teksti näidata ja
redigeerida saab JEditorPane ning mitme muu klassi abil.