domenica 9 maggio 2010

Java: programmazione grafica (1)

Netbeans, ma anche Eclipse, permettono la costruzione grafica delle interfacce in maniera molto semplice. I componenti vengono disposti all'interno dell'ambiente e la maggior parte del codice java viene generato automaticamente (bisogna poi scrivere il codice per gli eventi). Sebbene questo sia il metodo più semplice e veloce per realizzare una GUI (graphic user interface) è opportuno conoscere cosa c'è effettivamente dietro. Può sempre capitare di dover mettere mano al codice, meglio quindi non dimenticare almeno le basi (e vi assicuro che capita).
Nelle prime versioni di Java la libreria di riferimento per le GUI era la libreria AWT (abstract windows toolkit) che delegava al sistema operativo il compito di disegnare i componenti. La stessa applicazione, allora, risultava diversa (graficamente) in ogni sistema operativo! Inoltre, per stabilire lo stesso comportamento per ogni componente venne individuato un insieme minimo di componenti (comuni quindi ai sistemi operativi). La gestione di tali componenti avveniva tramite dei peer che ne traducevano il comportamento.
La libreria da tenere in considerazione per questo genere di cose è la libreria Swing (che estende la vecchia AWT mantenendo la compatibilità con la stessa, ora usata solo per la gestione degli eventi). L'obiettivo di Swing è quello di offrire all'utente lo stesso risultato anche su piattaforme diverse (uno degli slogan sempre pubblicizzati da Sun per Java: write one, run everywhere)
In Java una finestra viene anche detta frame mentre la classe incaricata di istanziare la stessa è JFrame. Un frame è un contenitore di oggetti, o come vedremo a breve di pannelli e componenti dell'interfaccia grafica. Se vogliamo generare una finestra non ci resta che estendere la classe JFrame e descrivere nel costruttore le proprietà da attribuire alla finestra con uno dei seguenti metodi:
  • setTitle(String title): riceve come parametro una stringa, il titolo cioè da assegnare alla finestra;
  • setSize(int width, int height): riceve come parametro due interi (oppure un oggetto Dimension nell'altra versione del metodo: setSize(Dimension dimension)) per dimensionare la finestra;
  • setLocation(int x, int y): riceve come parametro due interi (oppure un oggetto Dimension nell'altra versione setLocation(Dimension dimension) per le coordinate da assegnare alla finestra. L'angolo in alto a sinistra dello schermo ha coordinate (0,0);
  • setBounds(int x, int y, int width, int height): con questo metodo possiamo assegnare all'istante sia le coordinate della finestra che le sue dimensioni;
  • setResizable(boolean resizable): riceve come paramentro un valore booleano che abilita/disabilita le operazioni di ridimensionamento della finestra;
  • setIconImage(Image icon): riceve come parametro il riferimento a un oggetto Image da associare alla finestra come icona;
  • setBackground(Color background): riceve come parametro un oggetto Color che verrà usato come colore di background per la finestra;
  • setUndecorated(boolean undecorated): permette di mostrare la finestra senza le decorazioni aggiunte dal sistema operativo. E' utile ad esempio per creare splash screen di applicazioni in fase di avvio delle stesse;
La sola istanza di un frame non ne abilita la visione sul desktop, essa avviene invocando sull'oggetto il metodo setVisible(boolean visible). Adesso il metodo show() è stato deprecato da Java che invita i programmatori a usare il nuovo metodo (esistente anche nelle versioni precedenti di Java). Tutti i metodi finora visti applicano al frame una proprietà senza ritornare alcun valore. Java mette a disposizione anche i metodi per interrogare i campi di un'oggetto JFrame, come ad esempio: isVisible() e getLocation().
Ecco un frame vuoto, senza componenti:

class MyFrame extends JFrame {
   public MyFrame(String title, int width, int height, boolean isResizable) {
      this.title=title;
      this.width=width;
      this.height=height;
      setSize(width,height);
      setTitle(title);
      if (isResizable) setResizable(true);
   }
   public void centered() {
      Toolkit system=Toolkit.getDefaultToolkit();
      Dimension screenSize=system.getScreenSize();
      int screenWidth=screenSize.width;
      int screenHeight=screenSize.height;
      this.setLocation((screenWidth/2)-(width/2),(screenHeight/2)-(height/2));
   }
   private String title;
   private int width;
   private int height;
   static final long serialVersionUID=-1L;
}


Ricordo che va ovviamente importato il package javax.swing con l'istruzione: import javax.swing.*. Il metodo centered() implementato nella classe permette di centrare la finestra nel monitor dell'utente! Come ricavare le dimensioni dello schermo?
Occorre chiamare il metodo (statico, quindi non necessita di oggetti per l'invocazione) getDefaultToolkit() della classe Toolkit. Sull'oggetto, ritornato accediamo alle dimensioni del desktop con la chiamata a getScreenSize(), che ritorna un oggetto Dimension. Ricavate le dimensioni dell'area di lavoro e disponendo di quelle del frame si calcola, poi, la coordinata dell'angolo superiore sinistro da assegnare alla finestra (ad esempio con setLocation()).
Ecco il main che costruisce il frame, notate qualcosa di particolare?

public class TestMyFrame {
   public static void main(String[] args) {
      MyFrame frame=new MyFrame("Test",400,400,true);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.centered();
      frame.setVisible(true);
   }
}


La chiamata al metodo setDefaulCloseOperation() serve a specificare il comportamento dell'applicazione quando il frame viene chiuso dall'utente. Cosa fare? Chiudere tutta l'applicazione? Mostrare un nuova finestra? In questo esempio la chiusura della finestra fa terminare l'applicazione, ciò avviene passando al metodo la costante (della classe JFrame) EXIT_ON_CLOSE. Altre possibili opzioni sono:
  • DO_NOTHING_ON_CLOSE: non fare nulla alla chiusura del frame;
  • HIDE_ON_CLOSE: il frame viene in realtà nascosto (è come fare frame.setVisible(false). La finestra può essere resa nuovamente visibile;
  • DISPOSE_ON_CLOSE: nasconde e libera tutte le risorse impegnate dalla finestra (che dovrà essere creata di nuovo, se occorre);

Nell'esempio ho aggiunto al frame altri componenti: un pannello con un immagine e una stringa. Vi piace? Ci occuperemo dei pannelli in uno dei prossimi articoli.

Nessun commento:

Posta un commento