De la apariţia limbajului Java, bibliotecile de clase care oferă servicii grafice au suferit probabil cele mai mari schimbări în trecerea de la o versiune la alta. Acest lucru se datorează, pe de o parte dificultăţii legate de implementarea noţiunii de portabilitate, pe de altă parte nevoii de a integra mecanismele GUI cu tehnologii apărute şi dezvoltate ulterior, cum ar fi Java Beans. In momentul actual, există două modalităţi de a crea o aplicaţie cu interfaţă grafică şi anume:
. AWT (Abstract Windowing Toolkit) - este API-ul iniţial pus la dispoziţie începând cu primele versiuni de Java;
. Swing - este parte dintr-un proiect mai amplu numit JFC (Java Foundation Classes) creat în urma colaborării dintre Sun, Netscape şi IBM, care se bazează pe modelul AWT, extinzând funcţionalitatea acestuia şi adăugând sau înlocuind unele componente pentru dezvoltarea aplicaţiilor GUI.
Este preferabil ca aplicaţiile Java să fie create folosind tehnologia Swing, deoarece aceasta pune la dispoziţie o paletă mult mai largă de facilităţi, însă nu se va renunţa complet la AWT deoarece aici există clase esenţiale, reutilizate în Swing[4].
Dezavantajul AWT-ului este că arhitecţii lui au fost nevoiţi să ia în considerare numai acele clase de obiecte grafice, care există într-o formă sau alta pe toate platformele. Aceasta a făcut ca numărul de clase de obiecte grafice din pachetul java.awt să fie destul de restrâns, renunţându-se la funcţionalităţile specifice numai anumitor platforme.
In principiu, crearea unei aplicaţii grafice presupune următoarele lucruri[4]:
. Design
- Crearea unei suprafeţe de afişare (cum ar fi o fereastră) pe care vor fi aşezate obiectele grafice (componente) care servesc la comunicarea cu utilizatorul (butoane, controale pentru editarea textelor, liste, etc);
- Crearea şi aşezarea componentelor pe suprafaţa de afişare la poziţiile corespunzătoare;
. Funcţionalitate
- Definirea unor acţiuni care trebuie să se execute în momentul când utilizatorul interacţionează cu obiectele grafice ale aplicaţiei;
- "Ascultarea" evenimentelor generate de obiecte în momentul interacţiunii cu utilizatorul şi executarea acţiunilor corespunzătoare, aşa cum au fost ele definite.
Pachetul javax.swing
Componentele Swing, spre deosebire de predecesoarele din versiunile Java anterioare, sunt implementate în întregime în Java. Aceasta are ca rezultat o mai bună compatibilitate cu platforme diferite decât în cazul folosirii componentelor AWT.
Unul din principalele deziderate ale tehnologiei Swing a fost să pună la dispoziţie un set de componente GUI extensibile care să permită dezvoltarea rapidă de aplicaţii Java cu interfaţă grafică competitivă din punct de vedere comercial. Cel mai important pachet, care conţine componentele de bază este javax.swing.
Orice interfaţă utilizator Java este compusă din următoarele elemente:
. Componente - orice poate fi plasat pe o interfaţă utilizator, cum ar fi butoane, liste de derulare, meniuri pop-up, casete de validare sau câmpuri de text.
. Containere - acestea reprezintă componente care pot conţine alte componente (de exemplu panouri, casete de dialog sau ferestre independente)
. Administratori de dispunere - reprezintă obiecte care definesc modul în care sunt aranjate (dispuse) componentele într-un container. Administratorul de dispunere nu este vizibil într-o interfaţă, însă sunt vizibile rezultatele "muncii" sale. Dispunerea componentelor interfeţei este de mai multe feluri: dispunere secvenţială, dispunere tabelară, dispunere marginală sau dispunere tabelară neproporţională.
1). Componente şi containere
Componentele Swing sunt derivate dintr-o singură clasă de bază, numită JComponent, care moşteneşte la rândul ei clasa Container din AWT. Componentele folosite pentru crearea interfeţelor grafice Swing pot fi grupate astfel[4]:
. Componente atomice:
- JLabel, JButton, JCheckBox, JRadioButton, JToggleButton, JScrollBar, JSlider, JProgressBar, JSeparator
. Componente complexe:
- JTable, JTree, JComboBox, JSpinner, JList, JFileChooser, JColorChooser, JOptionPane
. Componente pentru editare de text:
- JTextField, JFormattedTextField, JPasswordField, JTextArea, JEditorPane, JTextPane
. Meniuri:
- JMenuBar, JMenu, JPopupMenu, JMenuItem, JCheckboxMenuItem, JRadioButtonMenuItem
. Containere intermediare:
- JPanel, JScrollPane, JSplitPane, JTabbedPane, JDesktopPane, JToolBar
. Containere de nivel înalt
- JFrame, JDialog, JWindow, JInternalFrame, JApplet
Containerele reprezintă suprafeţe de afişare pe care pot fi plasate alte componente, eventual chiar alte containere. Superclasa componentelor de acest tip este Container, din modelul AWT.
Containerele de nivel înalt
Pentru a fi afişate pe ecran componentele grafice ale unei aplicaţii trebuie plasate pe o suprafaţă de afişare (container). Fiecare componentă poate fi conţinută doar într-un singur container, adăugarea ei pe o suprafaţă nouă de afişare determinând eliminarea ei de pe vechiul container pe care fusese plasată. Deoarece containerele pot fi încapsulate în alte containere, o componentă va face parte la un moment dat dintr-o ierarhie. Rădăcina acestei ierarhii trebuie să fie un aşa numit container de nivel înalt, care este reprezentat de una din clasele JFrame, JDialog sau JApplet.
În general orice aplicaţie Java independentă bazată pe Swing conţine cel puţin un container de nivel înalt reprezentat de fereastra principală a programului, instanţă a clasei JFrame.
Containerele intermediare (JPanel, JScrollPane, JTabbedPane, JSplitPane, JLayeredPane, JDesktopPane, JRootPane.) reprezintă suprafeţe de afişare cu ajutorul cărora pot fi organizate mai eficient componentele aplicaţiei, putând fi imbricate.
JPanel are aceeaşi funcţionalitate ca şi clasa Panel din AWT, fiind folosit pentru gruparea mai multor componente Swing şi plasarea lor împreună pe o altă suprafaţă de afişare. Gestionarul de poziţionare implicit este FlowLayout, acesta putând fi schimbat însă, chiar în momentul construirii obiectului JPanel, sau ulterior cu metoda setLayout. Adăugarea de componente se realizează ca pentru orice container, folosind metoda add( ).
JScrollPane este o clasă foarte importantă în arhitectura modelului Swing, deoarece oferă suport pentru derularea pe orizontală şi verticală a componentelor a căror reprezentare completă nu încape în suprafaţa asociată, nici o componentă Swing neoferind suport intrinsec pentru această operaţie.
Clasa JComponent este superclasa tuturor componentelor Swing, mai puţin a celor care descriu containere de nivel înalt JFrame, JDialog, JApplet. Deoarece JComponent extinde clasa Container, deci şi Component, ea moşteneşte funcţionalitatea generală a containerelor şi componentelor AWT, furnizând bineînţeles şi o serie întreagă de noi facilităţi[4].
Componente pentru editare de text
Componentele Swing pentru afişarea şi editarea textelor sunt grupate într-o ierarhie ce are ca rădăcină clasa JTextComponent din pachetul javax.swing.text. Clasele pot împărţite în trei categorii, corespunzătoare tipului textului editat:
1. Text simplu pe o singură linie
- JTextField - Permite editarea unui text simplu, pe o singură linie.
- JPasswordField - Permite editarea de parole. Textul acestora va fi ascuns, în locul caracterelor introduse fiind afişat un caracter simbolic, cum ar fi '*'.
2. Text simplu pe mai multe linii
- JTextArea - Permite editarea unui text simplu, pe mai multe linii.Orice atribut legat de stil, cum ar fi culoarea sau fontul, se aplică întregului text şi nu poate fi specificat doar unei anumite porţiuni. Uzual, o componentă de acest tip va fi inclusă într-un container JScrollPane, pentru a permite navigarea pe verticală şi orizontală dacă textul introdus nu încape în suprafaţa alocată obiectului. Acest lucru este valabil pentru toate componentele Swing pentru care are sens noţiunea de navigare pe orizontală sau verticală, nici una neoferind suport intrinsec pentru această operaţiune.
3. Text cu stil îmbogăţit pe mai multe linii
- JEditorPane - Permite afişarea şi editarea de texte scrise cu stiluri multiple şi care pot include imagini sau chiar diverse alte componente.
- JTextPane - Această clasă extinde JEditorPane, oferind facilităţi suplimentare pentru lucrul cu stiluri şi paragrafe.
Componente atomice
În categoria componentelor atomice sunt incluse componentele Swing cu funcţionalitate simplă, a căror utilizare este facilă şi în general asemănătoare cu a echivalentelor din AWT:
. Etichete: JLabel
. Butoane simple sau cu două stări:JButton, JCheckBox, JRadioButton; mai multe butoane radio pot fi grupate folosind clasa ButtonGroup, pentru a permite selectarea doar a unuia dintre ele.
. Componente pentru progres şi derulare: JSlider, JProgressBar, JScrollBar
. Separatori: JSeparator
Componente complexe
Clasa JList
Clasa JList descrie o listă de elemente dispuse pe una sau mai multe coloane, din care utilizatorul poate selecta unul sau mai multe. Uzual un obiect de acest tip va fi inclus într-un container de tip JScrollPane. Clasa oferă metode pentru selectarea unor elemente din cadrul programului setSelectedIndex, setSelectedIndices, etc. şi pentru obţinerea celor selectate la un moment dat getSelectedIndex, getSelectedIndices, etc..
Clasa JComboBox
Clasa JComboBox este similară cu JList, cu deosebirea că permite doar selectarea unui singur articol, acesta fiind şi singurul permanent vizibil. Lista celorlalte elemente este afişată doar la apăsarea unui buton marcat cu o săgeată, ce face parte integrantă din componentă. JComboBox funcţionează după aceleaşi principii ca şi clasa JList.
Clasa JTable
Clasa JTable permite crearea de componente care să afişeze o serie de elemente într-un format tabelar, articolele fiind dispuse pe linii şi coloane. Un tabel poate fi folosit doar pentru afişarea formatată a unor date, dar este posibilă şi editarea informaţiei din celulele sale. De asemenea, liniile tabelului pot fi marcate ca selectate, tipul selecţiei fiind simplu sau compus, tabelele extinzând astfel funcţionalitatea listelor. O serie de clase şi interfeţe necesare lucrului cu tabele se găsesc în pachetul javax.swing.table, acesta fiind aşadar cel ce trebuie importat.
2). Tratarea evenimentelor
Interfaţa grafică serveşte interacţiunii cu utilizatorul. De cele mai multe ori programul trebuie să facă o anumită prelucrare în momentul în care utilizatorul a efectuat o acţiune şi, prin urmare, componentele trebuie să genereze evenimente în funcţie de acţiunea pe care au suferit-o (acţiune transmisă de la tastatură, mouse, etc.). În limbajului Java, evenimentele sunt instanţe ale claselor derivate din AWTEvent[4].
Aşadar, un eveniment este produs de o acţiune a utilizatorului asupra unui obiect grafic, deci evenimentele nu trebuie generate de programator. In schimb, într-un program trebuie specificat codul care se execută la apariţia unui eveniment. Tratarea evenimentelor se realizează prin intermediul unor clase de tip listener (ascultător, consumator de evenimente), clase care sunt definite în pachetul java.awt.event. In Java, orice componentă poate "consuma" evenimentele generate de o altă componentă.
Dacă o clasă doreşte să răspundă unui eveniment utilizator, ea trebuie să implementeze o interfaţă care să prelucreze evenimentele. Aceste interfeţe se numesc interceptoare de evenimente (events listeners). Fiecare interceptor tratează un anumit tip de eveniment, iar o clasă poate implementa oricâte evenimente are nevoie[9]. Cele mai importante interceptoare de evenimente sunt:
. ActionListener - tratează evenimente de acţiune, care sunt generate de acţiunea unui utilizator asupra unei componente, cum ar fi execuţia unui clic pe un buton.
. WindowListener - tratează evenimente de ferestre, care sunt generate de maximizarea, minimizarea, mutarea sau închiderea ferestrelor.
. MouseListener - tratează evenimente de mouse, care sunt generate de clicuri cu mouse-ul, de pătrunderea indicatorului mouse-ului pe suprafaţa unei componente sau de părăsirea acesteia.
. FocusListener - tratează evenimente de selecţionare, care sunt generate, atunci când o componentă devine selectată sau când pierde acest atribut.
. AdjustmentListener - tratează evenimente de modificare a componentelor.
. ItemListener - tratează evenimente generate de modificarea stării unei componente).
. KeyListener - tratează evenimente care apar când utilizatorul apasă o anumită tastă.