MokaByte Numero  36  - Dicembre 99
Le Swing in pratica
II parte
di
Daniela Micucci
I Container nelle Swing


Con il primo articolo apparso il mese scorso, abbiamo iniziato l'esplorazione del mondo Swing di Java. Continuiamo oggi con una panoramica sui Container che fanno parte delle Swing. Le novità sono molte e piacevoli.
I Container, come dice il nome stesso, sono dei contenitori in grado di includere componenti grafiche (bottoni, etichette di testo, liste, immagini, etc.). Nelle Swing esistono tre categorie di Container: di alto livello, di utilizzo generale (o intermedi) e specializzati. Ogni categoria contiene un sottoinsieme di contenitori ciascuno dei quali è indirizzato ad un uso specifico. Quella che segue è una panoramica di ciascuna categoria con l'intento di mostrare l'utilizzo di quei Container fondamentali nella costruzione di GUI, analizzando le differenze con i corrispondenti presenti nelle AWT. Nei prossimi numeri di MokaByte verranno analizzati più dettagliatamente i contenitori più specifici. 
 
 

I Container di alto livello
Iniziamo con quelli un pochino più complessi, ma essenziali se si vuole costruire una qualsiasi interfaccia grafica, sia applicazione che applet. Ogni componente grafica per poter essere visualizzata deve appartenere ad una gerarchia di contenimento alla radice della quale deve esserci un container denominato top-level (o di alto livello). Ciò vuol dire che ogni programma scritto in Java che usa le Swing ha almeno un Container di questo tipo. Nelle Swing esistono 4 Container top-level, e precisamente JFrame, JDialog, JApplet e JInternalFrame. Per comprendere invece cosa sia una gerarchia di contenimento, vediamo un esempio pratico. Se si osserva la figura sottostante, per realizzarla si è dovuto far uso di un container di alto livello (JFrame), di una etichetta di testo (JLabel), di un pannello (JPanel) e di un bottone (JButton).

JFrame è il contenitore di alto livello che occorre per rendere visibili le componenti grafiche per applicazioni grafiche. JPanel, come vedremo, è un contenitore che permette di raggruppare componenti. JButton e JLabel sono componenti elementari che permettono di realizzare particolari widget. La gerarchia di contenimento risultante è quella mostrata nella figura sottostante.

La novità introdotta con le Swing consiste nella presenza, in ogni contenitore di alto livello, di un oggetto chiamato ContentPane (di tipo Container) delegato a contenere i componenti grafici aggiunti in maniera diretta al Container. Nell'esempio, l'etichetta di testo e il pannello non sono realmente contenuti nel JFrame, ma sono contenuti nel ContentPane del JFrame. Questo cambiamento rende necessario modificare il solito approccio di aggiunta di componenti grafiche a cui eravamo abituati con le AWT. Più precisamente, per realizzare la finestra della figura con AWT si scrive:

...
Frame f = new Frame();
f.setTitle("La gerarchia di contenimento");
Panel p = new Panel();
p.add(new Button("bottone"));
f.add("Center", new Label("Premi il bottone e prova"));
f.add("South", p);
...
Per realizzare la stessa cosa con le Swing, si scrive invece:
...
JFrame f = new JFrame();
f.setTitle("La gerarchia di contenimento");
JPanel p = new JPanel();
p.add(new JButton("bottone"));
f.getContentPane().add("Center", new JLabel("Premi il bottone e prova"));
f.getContentPane().add("South", p);
...
Non è quindi più possibile eseguire un add() diretto su un Container di alto livello, ma occorre eseguirlo sul loro ContentPane. Ogni Container di questo tipo pubblica il metodo necessario ad ottenere il suo ContentPane: getContentPane() che restituisce un oggetto di tipo Container. Realmente le cose sono un pochino più complesse e la figura sottostante vuole cercare di chiarire la situazione.

Ogni container di questo tipo si appogia su un contenitore intermedio che si chiama JRootPane. È quest'ultimo che gestisce il ContentPane, l'eventuale menubar e altri due contenitori intermedi (JLayredPane e GlassPane). Di norma non è necessario interagire direttamente con il JRootPane, basta solo "colloquiare" con il ContentPane se si vuole unicamente aggiungere componenti ad un Container di alto livello o modificare il layout manager. Anche se si devidera inserire una menubar, la presenza del JRootPane risulta totalmente trasparente all'utente: il metodo necessario (setJMenuBar()) è, infatti, pubblicato da ciascun Container di alto livello. L'interazione con il JRootPane diventa necessaria solo nel momento in cui si voglia, per esempio, intercettare un evento da mouse su tutto il Container di alto livello e non sui singoli componenti presenti in esso (si lavora con il GlassPane), oppure se si desidera modificare l'overlapping delle componenti (si lavora con il JLayredPane). Al momento non entriamo in merito all'utilizzo del JRootPane. È da sottolineare che tra i contenitori di alto livello compare anche la classe JApplet che è la corrispondente della classe Applet a cui siamo abituati. Ciò vuol dire che, alla luce del discorso fatto sopra, con le Swing è possibile ora creare applet che possiedono una menubar!

I Container intermedi

Fanno parte di questa categoria quei contenitori che non hanno un aspetto grafico visibile, ma che fanno da valido supporto nella disposizione delle componenti grafiche. L'esempio più evidente è la classe JPanel che rappresenta un pannello trasparente. Tale classe si comporta esattamente come l'analoga presente nelle AWT: la classe Panel. L'utilità di questi contenitori intermedi sarà più chiaro nel prossimo articolo in cui si tratteranno i gestori del posizionamento delle componenti grafiche su di un Container: i layout manager. Se non si fa utilizzo di layout manager, probabilmente le classi presenti in questa categoria sono del tutto inutili, ma come si vedrà in seguito, disporre componenti grafiche per punti non è la via più corretta per una buona resa grafica senza prendere gli opportuni accorgimenti.

I Container specifici

Le Swing contengono una serie di Container atti a fornire determinati servizi. Citiamo un esempio: se un'immagine ha dimensioni maggiori rispetto allo spazio a lei destinato, occorre gestire svariate cose, tra cui la porzione di area visibile e lo scrolling. Il JScrollPane, che appartiene a questa categoria di Container, è stato implementato appositamente con il compito di gestire in automatico lo scrolling e l'area visibile. Questo è solo un esempio di container specifico atto a risolvere una particolare modalità di visualizzazione. Esiste però una caratteristica comune a tutti: se non si vogliono realizzare interfacce grafiche complesse e ci si limita, quindi, ad un utilizzo standard di questi container, le operazioni da eseguire sono realmente molto semplici. Di seguito è riportano un esempio di utilizzo della classe JScrollPane che realizza il programma riportato nella figura sotto. 


 
 
 
 
 
 
 

Il sorgente:

import javax.swing.*;
public class TestScrollPane extends JFrame
{
        public TestScrollPane()
        {
                super("Buon Natale a tutti i lettori di MokaByte!");
                ImageIcon image = new ImageIcon("natale.jpg");
                JLabel label = new JLabel(image);
                JScrollPane scroll = new JScrollPane(label);
                getContentPane().add(scroll);
                setSize(300, 200);
                setVisible(true);
        }

        public static void main(String a[])
        {
                new TestScrollPane();
        }
}

Di Container specifici nelle Swing ce ne sono molti: esistono container in grado di scrollare in automatico un oggetto (JScrollPane), gestire lo spazio da destinare a due container mediante un'azione del mouse (JSplitPane), visualizzare una serie di pannelli con etichetta (JTabbedPane), visualizzare testo e fornire capacità basi di editing (JTextPane e JEditorPane)...Nei prossimi articoli entreremo un po' più in dettaglio su ciascun di questi.
 

MokaByte rivista web su Java
MokaByte ricerca nuovi collaboratori
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it