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.