Un
file chooser e' un oggetto grafico che permette di navigare il file system
e di selezionare uno o piu' file su cui eseguire una determinata operazione.
Qualunque applicazione grafica ne utilizza uno per facilitare le operazioni
su disco. JFileChooser offre questa funzionalita' attraverso una accessoriata
finestra modale.
Figura
1 - Un esempio di JFileChooser
Possiamo
creare un'istanza di JFileChooser utilizzando questi costruttori:
-
JFileChooser()
:crea un JFileChooser che punta alla home directory dell'utente.
-
JFileChooser(File
currentDirectory):
crea un JFileChooser che punta alla directory specificata dal parametro.
Per
visualizzare un JFileChooser possiamo ricorrere alla seguente coppia di
metodi, che restituiscono un intero:
-
int
showOpenDialog(Component parent):
visualizza un JFileChooser per apertura file.
-
int
showSaveDialog(Component parent):
visualizza un JFileChooser per salvataggio file.
l'intero
che viene restituito puo' assumere uno di questi tre valori:
-
JFileChooser.CANCEL_OPTION
-
JFileChooser.APPROVE_OPTION
-
JFileCHooser.ERROR_OPTION
il programmatore
puo' decidere cosa fare dei files selezionati basandosi su queste risposte.
Entrambi
i metodi richiedono inoltre che venga passato come parametro un componente:
di norma si passa un reference al JFrame principale, che verra' bloccato
per tutta la durata dell'operazione. Passando null come parametro, il JFrame
verra' visualizzato al centro dello schermo e risultera' indipendente dalle
altre finestre.Per conoscere il risultato dell'interrogazione possiamo
usare i seguenti metodi:
-
File
getCurrentDirectory():
restituisce la directory corrente
-
File
getSelectedFile():
restituisce il file selezionato.
-
void
setCurrentDirectory(File dir):
imposta la directory di lavoro.
-
void
setSelectedFile(File file):
imposta il file selezionato.
Alcuni
metodi permettono un uso piu' avanzato di JFileChooser:
-
void
setDialogTitle(String dialogTitle):
imposta il titolo del JFileChooser.
-
void
setFileSelectionMode(int mode):
permette di abilitare il JFileChooser a selezionare solo files, solo directory
o entrambe, utilizzando come parametro uno dei seguenti valori:
-
JFileChooser.FILES_ONLY
-
JFileChooser.DIRECTORIES_ONLY
-
JFileChooser.FILES_AND_DIRECTORIES
-
void setMultiSelectionEnabled(boolean
b): abilita o disabilita la possibilita' di selezionare piu' di un file
per volta. In questo caso, per interrogare lo stato, si ricorrera' ai seguenti
metodi:
-
void
setSelectedFiles(File[] selectedFiles):
imposta come "selezionati" il gruppo di files passati come parametro.
-
File[]
getSelectedFiles():
restituisce un vettore contenente i files selezionati dall'utente.
Nelle
seguenti righe vediamo una tipica procedura che fa uso di JFileChooser;
nel prossimo paragrafo illustreremo un uso pratico di questo componente
all'interno di un'applicazione.
class
MyFrame extends JFrame {
....
fileChooser = new JFileChooser();
int response = fileChooser.showOpenDialog(this);
if(response==JFileChooser.APPROVE_OPTION) {
File f = fileChooser.getSelectedFile();
// qui viene eseguita l'operazione sul file
}
....
}
JTextArea
Il
package Swing dispone di un insieme completo di componenti grafici per
il trattamento di testi: JTextComponent, JTextField, JPasswordField, JTextArea,
JEditorPane, JTextPane.
Il
primo componente dell'elenco e' la superclasse astratta da cui discendono
tutti gli altri Text Component: esso definisce l'interfaccia di programmazione
e una prima implementazione di tutte le funzionalita' normalmente
presenti su editor di testo, come ad esempio la possibilita' inserire caratteri
da tastiera; quella di spostare il cursore in qualunque punto del documento
utilizzando il mouse o i tasti cursore; la possibilita' di operare selezioni
su gruppi contigui di caratteri al fine di eseguire su di essi una qualunque
operazione di editing nonche' i metodi per operare sulla clipboard di sistema
(che permette di copiare ed incollare testi anche tra programmi java e
programmi nativi) e quelli per leggere il documento da uno stream
di input o per inviarlo ad uno di output.
Nei
paragrafi precedenti abbiamo analizzato il funzionamento di JTextField,
un componente che permette di editare una singola riga di testo; ora ci
occuperemo di JTextArea, un oggetto grafico da utilizzare quando si intende
lavorare su testi di lunghezza media, con l'unica limitazione di permettere
l'utilizzo di un unico carattere, un unico stile ed un unico colore per
tutto il documento.
Nei
casi in cui si desideri lavorare su documenti complessi, senza subire limiti
nella scelta di font, stile o dimensioni, e' possibile utilizzare JEditorPane
e JTextPane, oggetti grafici che permettono di lavorare su formati testo
come RTF o HTML e con la possibilita' aggiuntiva di arricchire i testi
con immagini o componenti attivi. La complessita' di questa coppia di componenti
impedisce una trattazione in questa sede (essi richiederebbero un libro
a se stante); uno sguardo approfondito a JTextArea sara' comunque piu'
che sufficiente per rompere il ghiaccio con questa famiglia di componenti.
JTextArea API
La
via piu' breve per creare una JTextArea e' attraverso il costruttore privo
di parametri; altri costruttori permettono di specificare il numero di
righe e di colonne e la composizione iniziale del testo. E' importante
ricordare che JTextArea, al contrario del suo equivalente AWT, non dispone
di barre laterali di scorrimento; per questa ragione e' indispensabile,
all'atto della sua creazione, inserirlo dentro un JScrollPane, come si
puo' vedere nelle righe successive
...
JTextArea ta = new JTextArea();
JScrollPane scroll = new JScrollPane(ta);
getContentPane().add(BorderLayout.CENTER,scroll);
...
-
JTextArea():
Crea una JTextArea
-
JTextArea(String
text, int rows, int columns):
crea una JTextArea con il testo specificato dalla stringa text, e le dimensioni
specificate dai parametri rows e columns.
Possiamo
editare il testo nel componente direttamente con la tastiera e il mouse,
o da programma ricorrendo ad alcuni metodi. Questi metodi richiedono come
parametro un valore intero, che specifica la posizione del cursore rispetto
all'inizio del documento: se la nostra text area contenesse nella prima
riga la frase "La vispa Teresa" e nella seconda "avea tra l'erbetta", potremmo
dire che la parola "Teresa" e' compresa tra gli offset 9 e 15, mentre "erbetta"
si trova tra gli indici 27 e 34 (contando anche il ritorno carrello).
-
void
setText(String t):
cancella il precedente contenuto del componente e lo rimpiazza con la stringa
specificata.
-
String
getText():
restituisce il testo contenuto all'interno del componente.
-
String
getText(int offs, int len):
restituisce il testo che parte dalla posizione specificata dal primo
parametro, della lunghezza specificata dal secondo.
-
void
insert(String str, int pos):
inserisce il testo contenuto nella stringa nella posizione specificata
dal parametro.
-
void
append(String str):
inserisce il contenuto della stringa in coda al documento.
-
void
replaceRange(String str, int start, int end):
rimpiazza la sezione di testo compresa tra start ed end con la stringa
specificata.
In alternativa
possiamo inizializzare il componente a partire da uno stream.
-
void
read(Reader in, Object desc):
legge il testo da uno stream (il secondo parametro puo' essere messo a
null)
-
void
write(Writer out):
salva il testo su uno stream.
Un
gruppo di metodi permette di conoscere la posizione attuale del cursore
ed eventualmente modificarla: tra questi metodi ci sono anche quelli che
permettono di operare selezioni, ovvero di mettere in evidenza una porzione
di testo contigua, indicandone l'inizio e la fine.
-
int
getCaretPosition():
restituisce la posizione del cursore a partire dall'inizio del documento.
-
void
setCaretPosition(int position):
sposta il cursore alla posizione specificata.
-
void
moveCaretPosition(int pos)
: muove il cursore fino alla posizione specificata, evidenziando il testo
tra la nuova posizione e quella precedente.
-
void
select(int selectionStart, int selectionEnd)
: seleziona il testo situato tra la posizione iniziale e quella finale
specificate dai parametri.
-
String
getSelectedText():
restituisce il testo contenuto nella selezione.
-
void
replaceSelection(String content):
rimpiazza l'attuale selezione con il testo contenuto nella stringa.
-
int
getSelectionStart():
restituisce il punto di inizio della selezione
-
int
getSelectionEnd() :
restituisce il punto finale della selezione
Possiamo
operare sulla clipboard di sistema attraverso i metodi
-
void
copy()
-
void
cut()
-
void
paste()
-
void
selectAll()
Infine
possiamo impostare con i seguenti metodi alcune importanti proprieta'
-
void
setFont(Font font)
: imposta il font
-
void
setForeground(Color fg)
: imposta il colore del testo
-
void
setBackground(Color bg)
: imposta il colore dello sfondo
-
void
setEditable(boolean b) :
imposta il componente come editabile o non editabile.
Sviluppare un'applicazione
grafica complessa
Le
nozioni apprese fino ad ora permettono di affrontare lo studio di un'applicazione
grafica di una discreta complessita'. Le seguenti righe permettono di realizzare
un piccolo editor di testo perfettamente funzionante, utilizzando JTextArea,
una JToolBar, una JMenuBar, un JFileChooser e mostrando un utilizzo pratico
delle Action. Viene inoltre illustrato, all'interno dei metodi loadText()
e saveText(), come sia possibile inizializzare un Text Component
a partire da un file su disco.
Figura
2 - Con appena un centinaio di righe e' possibile
realizzare
un utile text editor
import
javax.swing.*;
import
javax.swing.text.*;
import
java.awt.*;
import
java.awt.event.*;
import
java.io.*;
public
class TextEditor extends JFrame {
private JTextComponent editor;
private JFileChooser fileChooser;
protected Action loadAction;
protected Action saveAction;
protected Action cutAction;
protected Action copyAction;
protected Action pasteAction;
public TextEditor() {
super("TextEditor");
setSize(300,300);
createActions();
JMenuBar menuBar = createMenuBar();
JToolBar toolbar = createToolBar();
editor = createEditor();
JComponent centerPanel = createCenterComponent();
getContentPane().add(BorderLayout.NORTH,toolbar);
getContentPane().add(BorderLayout.CENTER,centerPanel);
setJMenuBar(menuBar);
fileChooser = new JFileChooser();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
protected void createActions() {
loadAction = new AbstractAction("Open", new ImageIcon("Open24.gif")) {
public void actionPerformed(ActionEvent e) {
loadText();
}
};
saveAction = new AbstractAction("Save", new ImageIcon("Save24.gif")) {
public void actionPerformed(ActionEvent e) {
saveText();
}
};
cutAction = new AbstractAction("Cut", new ImageIcon("Cut24.gif")) {
public void actionPerformed(ActionEvent e) {
editor.cut();
}
};
copyAction = new AbstractAction("Copy", new ImageIcon("Copy24.gif")) {
public void actionPerformed(ActionEvent e) {
editor.copy();
}
};
pasteAction = new AbstractAction("Paste", new ImageIcon("Paste24.gif"))
{
public void actionPerformed(ActionEvent e) {
editor.paste();
}
};
}
protected JToolBar createToolBar() {
JToolBar tb = new JToolBar();
tb.add(loadAction);
tb.add(saveAction);
tb.addSeparator();
tb.add(cutAction);
tb.add(copyAction);
tb.add(pasteAction);
return tb;
}
protected JMenuBar createMenuBar() {
JMenu menu = new JMenu("Menu");
menu.add(loadAction);
menu.add(saveAction);
menu.addSeparator();
menu.add(cutAction);
menu.add(copyAction);
menu.add(pasteAction);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
return menuBar;
}
protected JComponent createCenterComponent() {
if(editor == null)
editor = createEditor();
return new JScrollPane(editor);
}
protected JTextComponent createEditor() {
return new JTextArea();
}
public void loadText() {
int response = fileChooser.showOpenDialog(this);
if(response==JFileChooser.APPROVE_OPTION) {
try {
File f = fileChooser.getSelectedFile();
Reader in = new FileReader(f);
editor.read(in,null);
setTitle(f.getName());
}
catch(Exception e) {}
}
}
public void saveText() {
int response = fileChooser.showSaveDialog(this);
if(response==JFileChooser.APPROVE_OPTION) {
try {
File f = fileChooser.getSelectedFile();
Writer out = new FileWriter(f);
editor.write(out);
setTitle(f.getName());
}
catch(Exception e) {}
}
}
public static void main(String argv[]) {
TextEditor t = new TextEditor();
}
}
Il
metodo createActions() riesce a definire cinque classi in appena trenta
righe di codice facendo uso delle classi anonime. L'uso di classi anonime
in questo contesto e' giustificato dal desiderio di rendere il programma
molto compatto; su progetti di dimensioni maggiori, si consiglia comunque
di ricorrere al piu' chiaro costrutto delle classi interne.
Questo
programma vuole anche dare una dimostrazione di costruzione modulare di
interfacce grafiche: come si puo' notare, il costruttore genera gli elementi
dell'interfaccia grafica ricorrendo ad un gruppo di "metodi fabbrica" (Factory
Method), ovvero metodi protected caratterizzati dal prefisso "create" (creeateToolBar(),
createMenuBar(), createCenterComponent() e createEditor()). Questa scelta
offre la possibilita' di creare sottoclassi del programma che implementino
una differente composizione della GUI semplicemente sovrascrivendo questi
metodi, e lasciando inalterato il costruttore. Se ad esempio disponessimo
di un'ipotetica HTMLTextArea e volessimo creare un editor HTML, ci basterebbero
appena cinque righe per adattare il nostro editor ad una nuova funzione.
public
class HTMLTextEditor extends TextEditor {
protected JTextComponent createEditor() {
return new HTMLTextArea();
}
}
In
uno dei prossimi paragrafi verra' presentato un esempio concreto che permettera'
di apprezzare i vantaggi di questa scelta di progettazione.
Conclusioni
Con
questo articolo si conclude la panoramica sui componenti grafici presenti
in Swing. Le conoscenze maturate dall'inizio del corso ci hanno finalmente
permesso di illustrare la costruzione di un'applicazione grafica semplice,
compatta e funzionale. Vi invito a sperimentare delle soluzioni personali,
utilizzando quanto appreso fino ad ora o modificando gli esempi presentati:
quest'ultima attivita' e' sicuramente la via migliore per impratichirsi
nella stesura del codice.
Nel
prossimo articolo affronteremo lo studio di alcuni contenitori specializzati:
JSplitPane, JTabbedPane e JDesktopPane.
Gli
esempi descritti nell'articolo possono essere scaricati qui |