JSplitPane
JSplitPane
e' un pannello formato da due aree, separate da una barra mobile; al suo
interno e' possibile disporre una coppia di componenti, affiancati lateralmente
o uno sopra l'altro. Il divisore puo' essere trascinato per impostare l'area
da assegnare a ciascuno dei due componenti, rispettando la dimensione minima
dei componenti in esso contenuti. Usando JSplitPane in abbinamento a JScrollPane
possiamo ottenere una coppia di pannelli ridimensionabili.
Il
seguente programma crea una finestra con uno JSplitPane al suo interno:
nel pannello superiore monta un'immagine JPEG, in quello inferiore una
TextArea sulla quale si possono annotare commenti. Per avviarlo e' necessario
specificare sulla riga di comando il percorso di un file JPEG o GIF (ad
esempio java JSplitDemo immagine.jpg)
Figura
1 - Un esempio di Split Pane
import
javax.swing.*;
import
java.awt.*;
public
class JSplitDemo extends JFrame {
public JSplitDemo(String fileName) {
super("JSplitPane");
setSize(300,250);
// costruisce un pannello contenente un'immagine
ImageIcon img = new ImageIcon(fileName);
JLabel picture = new JLabel(img);
JScrollPane pictureScrollPane = new JScrollPane(picture);
// crea un pannello contenente una TextArea
JTextArea comment = new JTextArea();
JScrollPane commentScrollPane = new JScrollPane(comment);
// Crea uno SplitPane verticale con i due
// pannelli al suo interno
JSplitPane splitPane = new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
pictureScrollPane,
commentScrollPane);
splitPane.setOneTouchExpandable(true);
splitPane.setDividerLocation(190);
splitPane.setContinuousLayout(true);
// aggiunge lo SplitPane al Frame principale
getContentPane().add(splitPane);
setVisible(true);
}
public
static void main(String argv[]) {
if(argv.length==1) {
JSplitDemo b = new JSplitDemo(argv[0]);
}
else
System.out.println("usage JSplitDemo <filename>");
}
}
JSplitPane API
Nell'esempio
siamo ricorsi ad un costruttore che permette di impostare le piu' importanti
proprieta' dello SplitPane con un'unica istruzione. Ovviamente sono disponibili
costruttori con un numero inferiore di parametri.
·
public JSplitPane(int orientamento, Component leftComponent, Component
rightComponent): Crea un JSplitPane con l'orientamento specificato dal
primo parametro e i componenti specificati dal secondo e dal terzo. Il
parametro orientamento puo' assumere i valori JSplitPane.HORIZONTAL_SPLIT
o JSplitPane.VERTICAL_SPLIT.
Per
specificare l'orientamento o per posizionare la coppia di componenti all'interno
dello SplitPane si puo' anche ricorrere ai metodi
-
void
setOrientation(int orientation):
Imposta l'orientamento del divisore.
-
void
setBottomComponent(Component comp):
Imposta il componente inferiore.
-
void
setTopComponent(Component comp):
Imposta il componente superiore.
-
void
setRightComponent(Component comp):
Imposta il componente di destra.
-
void
setLeftComponent(Component comp):
imposta il componente di sistra.
Un
gruppo di tre metodi permette di specificare la posizione del divisore
-
void
setDividerLocation(int location):
imposta la posizione assoluta del divisore.
-
void
setDividerLocation(double proportionalLocation):
imposta il divisore dividendo in modo proporzionale lo spazio disponibile
tra i due componenti. Se il valore e' 0.5 il divisore verra' posto a meta'
(questo metodo funziona correttamente solo se il pannello e' visibile)
-
void
setResizeWeight(double):
specifica come distribuire lo spazio che si viene a creare quando il componente
viene ridimensionato; se si imposta un valore di 0.5 lo spazio in piu'
viene diviso in maniera uguale tra i due componenti.
Per modificare
l'aspetto fisico del pannello sono diponibili le seguenti possibilita'
-
void
setDividerSize(int):
Imposta la dimensione in pixel della barra di divisione.
-
void
setOneTouchExpandable(boolean):
attivando questa proprieta', sulla barra apparira' una coppia di pulsanti
a freccia che permettono di espandere o collassare il divisore con un semplice
click
-
void
setContinuousLayout(boolean):
specifica se si desidera che il pannello venga ridisegnato durante il posizionamento
del divisore.
E'
possibile inserire i JSplitPane uno dentro l'altro, nel caso si desideri
avere piu' di due aree ridimensionabili. Ad esempio le seguenti istruzioni
creano uno Split Pane orizzontale contenente una TextArea ed uno Split
Pane verticale, il quale contiene a sua volta due TextArea.
Figura
2 - E' possibile creare SplitPane multipli
inserendone
uno dentro l'altro
JScrollPane
scroll1 = new JScrollPane(new JTextArea());
JScrollPane
scroll2 = new JScrollPane(new JTextArea());
JScrollPane
scroll3 = new JScrollPane(new JTextArea());
JSplitPane
internalSplit =
new JSplitPane(JSplitPane.VERTICAL_SPLIT,scroll1, scroll2);
JSplitPane
externalSplit =
new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,scroll3, internalSplit );
JTabbedPane
JTabbedPane
permette a diversi componenti di condividere lo stesso spazio sullo schermo;
l'utente puo' scegliere su quale componente operare premendo il Tab corrispondente.
Il tipico uso di questo componente e' nei pannelli di controllo,
nei quali si assegna ad ogni Tab la gestione di un insieme di funzioni
differente.
Oltre
all'innegabile utilita', questo componente presenta una modalita' di impiego
straordinariamente semplice: e' sufficiente creare il pannello ed aggiungervi
i vari componenti usando il metodo addTab(String title,Component
c), in cui il primo parametro specifica l'etichetta del tab, e il secondo
passa il componente. Il passaggio da un tab all'altro viene ottenuto clickando
con il mouse sul tab desiderato, senza bisogno di gestire gli eventi in
modo esplicito.
Nell'esempio
seguente viene creato un JTabbedPane al quale vengono aggiunti tre tab,
ognuno dei quali contiene un componente grafico diverso. L'esempio mostra
anche un esempio di gestione degli eventi: al cambio di tab viene aggiornato
il titolo della finestra.
Figura
3 - Un semplice JTabbedPane
import
javax.swing.*;
import
javax.swing.event.*;
public
class JTabbedPaneExample extends JFrame {
private JTabbedPane tabbedPane;
public JTabbedPaneExample() {
super("JTabbedPaneExample");
tabbedPane = new JTabbedPane();
JTextField tf = new JTextField("Primo Tab");
JButton b = new JButton("Secondo Tab");
JSlider slider = new JSlider(JSlider.HORIZONTAL,0,60,15);
tabbedPane.addChangeListener(new TabListener());
tabbedPane.addTab("One", tf );
tabbedPane.addTab("Two", b );
tabbedPane.addTab("Three", slider);
getContentPane().add(tabbedPane);
pack();
setVisible(true);
}
public class TabListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {
int pos = tabbedPane.getSelectedIndex();
String title = tabbedPane.getTitleAt(pos);
setTitle(title);
}
}
public static void main(String[] args) {
JTabbedPaneExample te = new JTabbedPaneExample();
}
}
Nell'esempio
abbiamo creato un JTabbedPane e vi abbiamo inserito tre Tab, ognuno dei
quali contiene un componente. Ovviamente e' possibile inserire all'interno
di un tab un intero pannello con tutto il suo contenuto:
....
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(BorderLayout.NORTH,new Button("Nord"));
....
panel.add(BorderLayout.SOUTH,new Button("Sud"));
tabbedPane.addTab("Pannello", panel);
....
JTabbedPane API
Per
creare un JTabbedPane possiamo ricorrere ai seguenti costruttori:
-
JTabbedPane():
Crea un JTabbedPane.
-
JTabbedPane(int
tabPlacement):
Crea un JTabbedPane con i tab posizionati in alto, in basso, a destra o
a sinistra secondo il valore del parametro: JTabbedPane.TOP, JTabbedPane.BOTTOM,
JTabbedPane.LEFT, o JTabbedPane.RIGHT.
Per
aggiungere o togliere componenti abbiamo un gruppo di metodi, tra i quali:
-
void
addTab(String title, Component component):
aggiunge un componente su un tab con il titolo specificato.
-
void
addTab(String title, Icon icon, Component component, String tip):
aggiunge un componente con il titolo, l'icona e il ToolTip specificati
dai parametri.
-
void
remove(Component component):
rimuove il Tab contenete il componente specificato.
-
void
removeAll():
Rimuove tutti i tab.
Un
gruppo di metodi permette di manipolare le proprieta' dei Tab
-
Component
getSelectedComponent():
restituisce il componente attualmente selezionato
-
void
setSelectedComponent(Component c):
imposta il Tab che contiene il componente specificato.
-
int
getSelectedIndex():
restituisce l'indice del componente attualmente selezionato
-
void
setSelectedIndex(int index):
imposta il tab che si trova nella posizione specificata dal parametro.
-
int
getTabCount():
restituisce il numero di Tab presenti nel Tabbed Pane.
-
int
indexOfComponent(Component component):
restituisce l'indice del componente passato come parametro.
-
String
getTitleAt(int index):
restituisce l'etichetta del tab nella posizione specificata.
La
gestione degli eventi su JTabbedPane e' abbastanza limitata, dal momento
che gli oggetti di tipo ChangeEvent non contengono nessuna informazione
sul tipo di evento che li ha generati (in pratica e' impossibile, per un
ascoltatore, distinguere tra un eventi di selezione, di aggiunta o di rimozione
di tab).
Possiamo
aggiungere o rimuovere un ascoltatore usando i metodi
-
void
addChangeListener(ChangeListener l)
-
void
removeChangeListener(ChangeListener l)
Gli
ascoltatori di tipo ChangeListener richiedono l'implementazione del metodo
void stateChanged(ChangeEvent e). Gli eventi di tipo ChangeEvent contengono
il solo metodo Object getSource(), che permette di ottenere un riferimento
all'oggetto che ha generato l'evento; per conoscere i dettagli dell'evento
(numero di tab, titolo ecc..) e' necessario interrogare direttamente il
componente sorgente.
JDesktopPane e
JInternalFrame
L'uso
combinato di JDesktopPane e JInternalFrame apre, al programmatore java,
un universo di possibilita': attraverso questi componenti e' possibile
realizzare ambienti tipo desktop, dotati di finestre interne, icone ed
oggetti grafici.
JInternalFrame
e' un oggetto grafico molto simile, nell'aspetto, nel comportamento e nell'interfaccia
di programmazione, ad un JFrame. La differenza piu' consistente tra questi
due oggetti e' che JInternalFrame, non essendo un Top Level Container,
non puo' comportarsi come radice di una gerarchia di contenimento; per
visualizzare oggetti di questo tipo e' necessario creare un'istanza JDesktopPane
e aggiungervi oggetti di tipo JInternalFrame usando il metodo add(component
c).
JInternalFrame frame = new JInternalFrame("Frame");
desktop = new JDesktopPane();
frame.setSize(120,80);
desktop.add(frame);
frame.setVisible(true);
Le
finestre create all'interno di JDesktopPane si comportano come finestre
di sistema, con l'unica differenza di essere confinate all'interno di questo
pannello: l'utente puo' spostarle, allargarle, ridurle ad icona e chiuderle,
ma non puo' in nessun caso trascinarle al di fuori dell'area a loro assegnata.
Si noti che e' obbligatorio assegnare una dimensione al JInternalFrame,
e che e' necessario chiamare il metodo setVisible(true) se si vuole rendere
visibile la nuova finestra. E' consigliabile anche prevedere una politica
di posizionamento, come nell'esempio a fine capitolo, altrimenti tutte
le finestre interne verranno posizionate nel margine in alto a sinistra
del JDesktopPane.
JDesktopPane API
Con
pochi metodi possiamo creare oggetti di tipo JDesktopPane ed impostarne
le proprieta'.
-
JDesktopPane():
crea un JDesktopPane.
-
JInternalFrame[]
getAllFrames() :
restituisce tutti i JInternalFrames contenuti.
-
JInternalFrame
getSelectedFrame():
restituisce il JInternalFrame attivo, o null se nessun JInternalFrame e'
attivo al momento.
-
void
setDragMode(int dragMode) :
imposta lo stile di trascinamento per il desktop pane. Sono disponibili
due scelte: JDesktopPane.LIVE_DRAG_MODE fa si' che il contenuto del frame
rimanga visibile durante il trascinamento; JDesktopPane.OUTLINE_DRAG_MODE
invece fa si' che durante il trascinamento venga spostata soltanto la sagoma
del frame, permettendo un refresh piu' rapido.
-
void
setSelectedFrame(JInternalFrame f):
imposta il JInternalFrame attivo.
JInternalFrame
API
L'interfaccia
di programmazione di JInternalFrame e' abbastanza complessa, e ricalca
il prototipo dell'API JFrame. Rispetto a quest'ultima, l'API JInternalFrame
fornisce un maggior controllo sulle proprieta' della barra del titolo e
sui controlli che essa deve contenere per chiudere, espandere, ridurre
ad icona e ridimensionare la finestra; il seguente costruttore permette
di impostare in un'unica istruzione tutte queste proprieta':
-
JInternalFrame(String
title, boolean resizable, boolean closable, boolean maximizable, boolean
iconifiable):
crea un JInternalFrame con le proprieta' specificate dai parametri.
I seguenti
metodi sono equivalenti a quelli presenti su JFrame.
-
Container
getContentPane():
restituisce il content pane di questo JInternalFrame.
-
void
setContentPane(Container c):
imposta il content pane.
-
void
pack():
fa in modo che i componenti interni vengano impostati alla dimensione ideale.
-
void
setDefaultCloseOperation(int operation):
imposta l'azione da eseguire alla pressione del tasto "close". Sono disponibili
le seguenti scelte:
-
WindowConstants.DO_NOTHING_ON_CLOSE:
nessun effetto.
-
WindowConstants.HIDE_ON_CLOSE:
nasconde la finestra (e' l'impostazione di default)
-
WindowConstants.DISPOSE_ON_CLOSE:
distrugge la finestra.
-
void
setJMenuBar(JMenuBar m)
: imposta la JMenuBar.
-
void
setTitle(String title):
imposta il titolo del frame interno JInternalFrame.
Questi
metodi invece sono presenti esclusivamente su JInternalFrame:
-
void
setSelected(boolean selected)
: seleziona o deseleziona il JInternalFrame.
-
JDesktopPane
getDesktopPane():
restituisce il JDesktopPane che contiene questo JInternalFrame.
-
Component
getFocusOwner() :
restituisce il JInternalFrame che ha il fuoco.
-
void
setFrameIcon(Icon icon):
imposta l'icona della titlebar.
-
void
toBack():
spinge "in sotto" questo JInternalFrame.
-
void toFront():
"tira su'" il JInternalFrame.
-
void
addInternalFrameListener(InternalFrameListener l):
aggiunge a questo JInternalFrame un InternalFrameListener.
-
void
removeInternalFrameListener(InternalFrameListener l):
rimuove un InternalFrameListener da questo JInternalFrame.
Modello degli
eventi di JInternalFrame
La
gestione degli eventi e' affidata ad oggetti di tipo InternalFrameListener
, che offrono un controllo totale degli eventi che possono capitare
ad un JInternalFrame.
:
Figura
4 - Il meccanismo di gestione degli eventi di JInternalFrame
Di
seguito ecco i metodi dell'interfaccia InternalFrameListener con la descrizione
del tipo di evento che ne provoca la chiamata.
-
void
internalFrameActivated(InternalFrameEvent e):
un internal frame e' stato attivato attivato.
-
void
internalFrameClosed(InternalFrameEvent e):
un internal frame e' stato chiuso.
-
void
internalFrameClosing(InternalFrameEvent e):
un internal frame sta' per essere chiuso.
-
void
internalFrameDeactivated(InternalFrameEvent e):
un internal frame e' stato disattivato.
-
void
internalFrameDeiconified(InternalFrameEvent e):
un internal frame e' stato de-iconificato.
-
void
internalFrameIconified(InternalFrameEvent e):
un internal frame e' stato ridotto ad icona.
-
void
internalFrameOpened(InternalFrameEvent e):
un internal frame e' stato aperto.
Un esempio
pratico
Ecco
ora un esempio completo: una fabbrica di JInternalFrame. Questo programma
presenta un JDesktopPane e una JToolBar, nella quale sono presenti i controlli
che permettono di creare dei JInternalFrame dopo averne impostate le proprieta'.
La politica di posizionamento viene implementata con delle formule matematiche
nel metodo createFrame(), che calcola le coordinate tenendo conto della
dimensione del frame, del desktop e dalla posizione dell'ultima finestra
visualizzata.
Figura
4 - Una fabbrica di JInternalFrame
import
javax.swing.*;
import
java.awt.event.*;
import
java.awt.*;
public
class InternalFrameExample extends JFrame {
private JDesktopPane desktop;
private int frameNumber = 0;
private int xPos = 0;
private int yPos = 0;
private JTextField titleTextField;
private JCheckBox resizableCheckBox;
private JCheckBox closableCheckBox;
private JCheckBox maximizableCheckBox;
private JCheckBox iconifiableCheckBox;
public InternalFrameExample() {
super("InternalFrameExample");
setSize(640,210);
JToolBar toolbar = createToolBar();
desktop = new JDesktopPane();
getContentPane().add(BorderLayout.WEST,toolbar);
getContentPane().add(BorderLayout.CENTER,desktop);
setVisible(true);
}
protected JToolBar createToolBar() {
JToolBar tb = new JToolBar(JToolBar.VERTICAL);
JPanel titlePanel = new JPanel();
titlePanel.setLayout(new FlowLayout());
JLabel titleLabel = new JLabel("Titolo");
titleTextField = new JTextField("Frame 0",10);
titlePanel.add(titleLabel);
titlePanel.add(titleTextField);
resizableCheckBox = new JCheckBox("Ridimensionabile");
closableCheckBox = new JCheckBox("Richiudibile");
maximizableCheckBox = new JCheckBox("Massimizzabile");
iconifiableCheckBox = new JCheckBox("Iconificabile");
JButton generateButton = new JButton("Genera
un JInternalFrame");
ActionListener listener = new GenerateButtonActionListener();
generateButton.addActionListener(listener);
titleTextField.addActionListener(listener);
tb.add(titlePanel);
tb.add(resizableCheckBox);
tb.add(closableCheckBox);
tb.add(maximizableCheckBox);
tb.add(iconifiableCheckBox);
tb.add(generateButton);
return tb;
}
protected JInternalFrame createFrame(String title,boolean resizable,boolean
closable,boolean maximizable,boolean iconifiable) {
// Crea il Frame secondo i parametri
JInternalFrame frame = new JInternalFrame(title,
resizable,
closable,
maximizable,
iconifiable);
frame.setSize(120,80);
// Aggiunge una Label al suo interno
JLabel titleLabel = new JLabel(title,JLabel.CENTER);
frame.getContentPane().add(titleLabel);
// Calcola la posizione del nuovo InternalFrame
int xSize = desktop.getWidth()-frame.getWidth();
int ySize = desktop.getHeight()-frame.getHeight();
int xStep = desktop.getWidth()/10;
int yStep = desktop.getHeight()/10;
xPos=(xPos+xStep)%xSize;
yPos=(yPos+yStep)%ySize;
frame.setLocation(xPos,yPos);
return frame;
}
class GenerateButtonActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String title = titleTextField.getText();
boolean resizable = resizableCheckBox.isSelected();
boolean closable = closableCheckBox.isSelected();
boolean maximizable = maximizableCheckBox.isSelected();
boolean iconifiable = iconifiableCheckBox.isSelected();
JInternalFrame frame = createFrame(title,
resizable,
closable,
maximizable,
iconifiable);
// aggiunge al JDesktopPane
desktop.add(frame);
// lo mette in cima agli altri JInternalFrame
frame.moveToFront();
// lo rende visibile
frame.setVisible(true);
titleTextField.setText("Frame "+String.valueOf(
frameNumber++));
}
}
public static void main(String[] args) {
InternalFrameExample frame = new InternalFrameExample();
}
}
Conclusioni
Questa
carrellata sui principali contenitori specializzati presenti su Swing chiude
il ciclo di articoli dedicata ai componenti grafici. Nel prossimo articolo
vedremo come abbellire i componenti Swing usando bordi, icone e tooltips.
L'esempio
descritto in questo articolo può essere trovato qui
|