Graphical User Interface (GUI) - Java Swing și JavaFX
În multe dintre aplicațiile pe care le veți dezvolta folosing Java, veți avea nevoie și de o interfață grafică adecvată: ferestre, butoane, câmpuri de editare, checkboxuri, etc. Există mai multe biblioteci de dezvoltare pentru interfețe grafice, cea mai cunoscută fiind Java Swing și cea mai nouă fiind JavaFX.
Java Swing
Pachetul care conține majoritatea claselor pentru aplicațiile Swing este java.swing dar sunt utilizate și multe din clasele din vechea biblotecă GUI, java.awt. Clasa principală pentru aplicații Java Swing este clasa javax.swing.JFrame.
Frame-ul este fereastra principală a unei interfețe grafice. Este elementul care are asociată bara de deasupra, care conține icon-ul, numele aplicației și cele trei butoane: minimize, maximize, close:
În continuare este prezentat un frame ce conține cele mai utilizate componente Swing:
Componente
Toate obiectele Swing, cu excepția clasei JFrame, moștenesc clasa javax.swing.JComponent, care la rândul ei moștenește (indirect) clasa java.awt.Container. Astfel, se creează o ierarhie de componente, fiecare element (numit parent) înglobând alte sub-componente (numite children). În continuare se vor prezenta elementele necesare realizării temei 6. Pentru descrierea altor elemente mai avansate, citiți tutorial-ul Oracle.
javax.swing.JPanel
JPanel este un container generic care poate conține alte elemente. Poate fi vizibil, schimbându-i-se culoarea background-ului, sau modelul marginii, sau invizibil, folosit doar pentru ierarhizarea conținutului. Este indicat să nu plasați alte obiecte direct pe un JFrame, ci doar un JPanel care să conțină restul de elemente. Acest lucru este foarte util și când aveți nevoie să schimbați complet elementele dintr-un JFrame, înlocuiți doar JPanel-ul.
javax.swing.JLabel
JLabel este un component utilizat pentru a afișa text sau imagini într-un container.
javax.swing.JButton
JButton este, cum îi spune și numele, un buton. Acesta poate avea afișat un text sau o imagine. De cele mai multe ori este utilizat asociindu-i-se un Event Handler de tip ActionListener (vezi #Event Handlers) care se declanșează când acesta este apăsat (se dă click pe el).
javax.swing.JTextField
JTextField reprezintă o zonă în care se poate introduce text scurt, de o singură linie. Și acestul element i se poate asocia un Event Handler de tip ActionListener care se declanșează când se apasă tasta Enter în zona de editare.
javax.swing.JTextArea
JTextArea reprezintă o zonă în care se poate introduce text de mai multe linii.
Layouts
O altă serie de clase necesară pentru implementarea unei interfețe grafice este setul de clase care extind interfața java.awt.LayoutManager. Aceste clase descriu modul în care elementele se așează într-un Container. Cele mai importante sunt:
java.awt.FlowLayout
FlowLayout este utilizat pentru a așseza elementele pe orizontală, până când nu mai încap, în care situație se trece pe rândul următor. Acesta este cel mai simplu tip de layout.
java.awt.GridLayout
GridLayout este utilizat pentru a așseza elementele într-o matrice cu număr configurabil de linii și coloane.
java.awt.BorderLayout
BorderLayout este utilizat pentru a așseza elementele dealungul celor patru margini și în centru, adică NORTH, SOUTH, EAST, WEST și CENTER. Un singur element poate fi plasat în fiecare din aceste poziții.
java.awt.CardLayout
CardLayout este utilizat pentru a adăuga mai multe componente unui Container din care doar unul este vizibil la un moment dat. Acest tip de layout este util pentru generarea de aplicații tip wizard în care utilizatorul trece de la o fereastră la alta cu ajutorul unor butoane Next și Previous.
Mai multe despre elemente de tip Layout, în tutorial-ul Oracle.
Event Handlers
Fiecare JComponent suportă o listă de evenimente la care e sensibil. Fiecărui eveniment i se poate asociaza o acțiune care se execută când acel eveniment se declanșează. De exemplu, când un buton este apăsat, sau când cursorul de la mouse a intrat în zona ocupată de componentă, sau când s-a tastat ceva într-o zonă de text, etc. Aceste handler-e sunt, de fapt, niște metode, definite în anumite interfețe. Aceste metode se excută în paralel cu programul principal (ca și thread-uri) în momentul în care evenimentul se declanșează. Metodele care adaugă un handler unui obiect sunt de forma:
- public void addActionListener(ActionListener _listener) - pentru evenimente de tip action, adică activarea unui component (click pe un buton, enter într-un text field, etc.);
- public void addMouseListener(MouseListener _listener) - pentru evenimente legate de mouse;
- etc.
Același handler poate fi asociat mai multor elemente, iar în acest caz, pentru a știi care obiect a generat evenimentul, se folosește metoda getSource() definită în clasa java.util.EventObject care este superclasă pentru toate obiectele primite ca argumente de metode de tip handler (java.awt.event.ActionEvent, java.awt.event.MouseEvent, etc.). Metoda getSource() întoarce o referință de tip Object la componenta de interfață care a generat evenimentul.
Mai multe despre handler-e, în tutorial-ul Oracle.
Exemplu
Vom descrie un JFrame care conține două JLabel, două JTextField, un JTextArea și un JButton. Când se apasă butonul, cele două JTextField se vor încărca cu valorile dimensiunii JFrame-ului și se va scrie un caracter x în JTextArea:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class FrameTest extends JFrame implements ActionListener {
// we define the elements used in
// the frame
private JPanel mainPanel;
private JLabel xLabel;
private JLabel yLabel;
private JTextField xField;
private JTextField yField;
private JTextArea textArea;
private JButton button;
public FrameTest(String _title){
// calling the constructor for JFrame to set the title
super(_title);
// initializing the components (method is implemented below)
initComponents();
// calling pack() defined in superclass to resize the frame according to
// contents
pack();
// displaying the frame
setVisible(true);
// select the default behaviour when closing the frame by clicking
// the X button on the bar: the application will exit
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] _args){
FrameTest _frame = new FrameTest("Frame Test");
}
private void initComponents() {
// setting the layout as FlowLayout
setLayout(new FlowLayout());
// creating the components
// the panel adds the components in
// a FlowLayout
mainPanel = new JPanel(new FlowLayout());
xLabel = new JLabel("X size (width):");
yLabel = new JLabel("Y size (height):");
xField = new JTextField(6); //6 columns (characters)
yField = new JTextField(6); //6 columns (characters)
textArea = new JTextArea(10, 10); //10 columns, 10 rows
button = new JButton("Click me!");
//adding components to panel
mainPanel.add(xLabel);
mainPanel.add(xField);
mainPanel.add(yLabel);
mainPanel.add(yField);
mainPanel.add(textArea);
mainPanel.add(button);
//adding scrollPane to frame
add(mainPanel);
// adding the listener to the button Component
button.addActionListener(this);
}
// this is the handler defined in the ActionListener interface
public void actionPerformed(ActionEvent _actionEvent) {
xField.setText(String.valueOf(this.getWidth()));
yField.setText(String.valueOf(this.getHeight()));
textArea.append("x");
}
}
Rezultatul arată așa:
Pentru a crea frame-uri mai complexe, trebuie să folosiți alte tipuri de LayoutManager, elemente de tip javax.swing.JScrollPane, sau, puteți utiliza un mediu de dezvoltare, gen Netbeans pentru a crea în mod vizual interfața.
JavaFX
JavaFX este cea mai nouă implementare a platformei de dezvoltare pentru interfețe GUI de client. Cu toate că este încă într-un stadiu incipient, are avantaje față de vechiul Swing. Versiunea 2.2, care a fost publicată pe 14 august 2012 este un pas înainte către o nouă generație de aplicații multimedia pe Internet. Conform site-ului Oracle, principalele avantaje ale JavaFX sunt:
- integrare completă cu Java SE și JDK, incepând cu versiunea 7, update 6 (7u6), ceea ce implică faptul că aplicațiile JavaFX vor putea fi dezvoltate și rulate de către orice client cu această verisune de Java;
- inițial JavaFX a fost un limbaj de scripting, dar acum Oracle pune la dispoziție un API pentru dezvoltarea aplicațiilor direct în Java, pentru un mai bun management și reutilizare a codului;
- un nou motor (engine) grafic, numit Prism, care face uz de accelerarea hardware oferită de GPU-urile moderne, precum și un nou manager de ferestre (Window Toolkit) numit Glass;
- un nou limbaj bazat pe XML, numit FXML, folosit pentru descrierea interfețelor grafice, astfel încât să nu fie nevoie de recompilarea codului la fiecare modificare;
- un nou engine multimedia, bazat pe GStreamer, care permite redarea de conținut multimedia;
- o componentă care poate afișa conținut web și care poate fi integrată în orice interfață grafică JavaFX;
- o serie de componente noi de interfață, precum grafice, tabele, meniuri și panouri;
- un sistem de a împacheta aplicațiile astfel încât acestea să fie livrate cu toate bibliotecile necesare execuției;
- portabilitate pe Linux, Windows și Mac OS X;
Componente
Ca și Java Swing, JavaFX se bazează pe o ierarhie de clase care implementează diferite componente și containere ce reprezintă elementele grafice. Analog clasei JFrame, în JavaFX, clasa care descrie fereastra principală a unei aplicații este javafx.stage.Stage. O aplicație JavaFX (spre deosebire de o aplicație Java obișnuită, care pornește cu metoda main()) trebuie să extindă clasa javafx.application.Application. Aceasta este o clasă abstractă, deci utilizatorul este obligat să definească metoda public void start(Stage _primaryStage), care este metoda de start a aplicației, analog metodei main: