Tecnologie - Classe Quarta robertomana.it Introduzione a Java Introduzione a Java Rev Digitale 1.0 del 01/09/2016 Introduzione al linguaggio …………………………………………..……………………….….….. Caratteristiche generali: …………………………………………..…………………………..….….. Le basi del linguaggio Java …………………………………………..…………………………….….. Gestione dell’input output …………………………………………..…………………………….….. Tipi di dato nativi e le classi base …………………………………………..………………………….. Boxing, Unboxing e Autoboxing …………………………………………..………………………….. Le stringhe …………………………………………..……………………………………..…….….. Il passaggio dei parametri …………………………………………..…………………………….….. La conversione fra i tipi …………………………………………..…………………………..….….. Le istruzioni base: condizionali e cicli …………………………………………..……………….….. Strutture dati semplici: vettori e matrici ………………………………………………………….….. Gestione delle eccezioni …………………………………………..…………………………….….. Gestione dei files di testo …………………………………………..…………………………….….. 2 2 5 5 6 6 7 8 9 10 10 11 12 Dichiarazione ed utilizzo delle classi …………………………………………..……………….….. Ereditarietà …………………………………………..………………………………….……….….. Overload e Override …………………………………………..……………………………….….. 13 15 15 Le librerie grafiche java - swing …………………………………………..………………..….….. Istanza ed inizializzazione di una nuova fom …………………………………….…………….….. Inserimento dei controlli all’interno della form ……………………………………………….….. La gestione degli eventi …………………………………………..…………………………….….. Gli eventi relativi alla form (window event) ……………………..…………………………….….. La gestione del layout ……………………………………………..…………………………….….. I principali controlli con relative Proprietà e Metodi ………………………………………….….. Le finestre di Dialogo …………………………………………..……………………………..….. 16 18 20 21 23 23 25 28 pag 1 Tecnologie - Classe Quarta robertomana.it Introduzione a Java JAVA Introduzione Il linguaggio fu originariamente sviluppato da James Gosling e altri ingegneri presso Sun Microsystems e venne presentato ufficialmente il 23 Maggio 1995 in occasione del SunWorld ‟95 (convegni annuali di Sun Microsystems), come strumento per la creazione di programmi x Internet. Nel 1993 nasce il primo browser internet (mosaic) (anno di nascita di Internet) Nel 1994 nasce Internet Netscape. Nel 1995 Netscape Corporation annuncia la scelta di dotare il suo celeberrimo browser della Java Virtual Machine. Questo segna una rivoluzione nel mondo di Internet, consentendo al programmatore di sviluppare applet che, interagendo con la Java Virtual Machine, consentono di creare pagine web interattive a livello client (ovvero le applicazioni vengono eseguite direttamente sulla macchina dell'utente, e non su un server remoto). Gli utenti possono così utilizzare giochi direttamente sulle pagine web ed usufruire di chat dinamiche e interattive. Nel 1995 (giugno) Netscape Corporation rilascia la prima versione di JavaScript, un linguaggio che consente l‟inserimento di apposite istruzioni direttamente all’interno delle pagine HTML, istruzioni interpretate dal browser che consentono all‟utente di eseguire semplici interazioni con la pagina HTML. Il fatto che i due linguaggi abbiano nomi simili è solo una trovata di marketing, dovuta all‟alleanza tra Netscape e Sun. Si tratta in effetti di due linguaggi con Modello Oggetti differenti, di cui Java consente di sviluppare applicazioni indipendenti che devono essere compilate, mentre Java Script consente di scrivere all‟interno della pagina html semplici script testuali che saranno poi interpretati dal browser. Nel 2010 il marchio Java è stato acquisito da Oracle Corporation, che ne è attualmente detentore. Tutte le varie implementazioni devono sottostare alle specifiche definite nello standard. La versione attuale è Java 1.7 detto in realtà Java 2 La sintassi di base (strutture di controllo, operatori, etc) è identica a quella del C/C++, con lo scopo di facilitare il passaggio da un ambiente all‟altro. Il nome Java Il linguaggio fu battezzato con questo nome perché gli stessi tecnici durante il lavoro di sviluppo amavano discutere del progetto davanti ad una tazzina caffè Java (caffè indonesiano; Java è la principale isola dell‟Indonesia). La tazza di caffè fumante è rimasto il simbolo di Java. Caratteristiche del linguaggio Java Java è un linguaggio di programmazione orientato agli oggetti, specificatamente progettato per essere il più possibile indipendente dalla piattaforma di esecuzione, in cui il codice compilato possa essere eseguito su piattaforme diverse senza dover essere ricompilato Il prodotto della compilazione è infatti in un formato chiamato bytecode (precompilato) che può essere eseguito (in realtà interpretato) da una qualunque implementazione di un processore virtuale detto Java Virtual Machine. Tradizionalmente i passi necessari per eseguire una applicazione erano i seguenti : Sorgente -> Compilatore -> Binario Cambiando la piattaforma hw non funziona più. Non è portabile. Con l’interprete non c‟è più bisogno di compilare. L‟interprete legge ed esegue riga per riga. Consuma molte più risorse, per cui è molto più lento, ma consente la portabilità. pag 2 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Un programma scritto su una piattaforma può poi essere eseguito su qualsiasi altra piattaforma dotata dell‟interprete. Altro vantaggio è che i programmi interpretati non hanno bisogno di installazioni, ma è sufficiente la presenza dell‟interprete. Già negli anni 80 con rm Cobol era stato utilizzato il concetto di interprete: edit file.cob rmcobol file.cob Java rappresenta una soluzione intermedia. La compilazione produce un codice intermedio che comunica con la Virtual Machine e non con il Sistema Operativo. E' sufficiente la presenza della Virtual Machine. La Controparte sta nella pesantezza. Per utilizzare programmi Java come Eclipse occorrono macchine prestanti con molta RAM. Sorgente -> Compilatore -> pseudoCodice -> Interprete Sorgente .java -> Compilatore javac -> byte code -> Interprete JVM $> edit pgm.java $> javac pgm.java : il compilatore produce il bytecode pgm.class $> java pgm : la JVM interpreta ed esegue il file pgm.class (scritto però senza estensione) Il compilatore produce un file con estensione .class che verrà interpretato dalla JVM. Java ad oggi è totalmente portabile. Esistono JVM per QUALSIASI SO. Creato un byte code con qualsiasi SO, questo potrà poi essere eseguito su qualsiasi altro SO. DotNet utilizza una tecnologia molto simile: Sorgente -> Compilatore -> MSIL -> Interprete CLR CLR = Common Language Runtime, macchina virtuale o framework. In realtà ogni funzione viene compilata Just In Time al primo accesso e tenuta in memoria. Esiste un CLR non ufficiale per Linux detto Mono Versioni La macchina virtuale esiste in diverse versioni: J2SE standard edition (tipica JRE Java Runtime Environment) J2EE enterprise edition versione più completa con tutte le librerie per lo sviluppo di applicazioni server (tipica SDK Software Development Kit detta anche JDK). J2ME micro edition (funzionalità ridotte per cellulari. Simbian (SO Nokia) aveva dentro una J2ME. Per sviluppare in Java non basta la JRE, ma ci vuole anche il compilatore. Occorre cioè l‟SDK Oggi JDK 7 che contiene compilatore + macchina virtuale versione Java 1.7 Evitare Open JDK. Versione Open di Oracle. Di solito non aggiornato e poco compatibile. I files JAR sono files contenenti un archivio compresso di classi java (libreria). Questo formato è direttamente utilizzabile dalla JVM senza necessità di decompressione. Le principali qualità di Java sono la semplicità, l‟elevata strutturalità e la robustezza Il garbage collector, tra le semplificazioni, è quella più palese. Un‟altra delle tante, meno evidente ma altrettanto importante, riguarda il passaggio dei parametri. I tipi primitivi possono essere passati solo per valore, gli oggetti solo per riferimento. Non esistono i record. pag 3 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Installazione e Definizione del percorso del compilatore Andare sul sito di Oracle e scaricare gratuitamente la JDK 7 Dopo di che su Windows occorre configurare una variabile d‟ambiente che consenta di poter eseguire il compilatore JAVAC (che si trova in JDK 7 / BIN) da qualsiasi cartella. A tal fine: Pannello di Controllo / Sistema, ultima voce a sinistra “Impostazioni di sistema Avanzate”, sottofinestra Avanzate pulsante Variabili d’ambiente, selezionare Nuova e digitare: nome -> PATH valore -> %PATH%;C:\Program Files\Java\jdk1.7.0_45\bin Questa configurazione è legata all‟utente, per cui deve essere rifatta ogni volta che la macchina viene utilizzata da un nuovo utente. IDE Eclipse (oracle) Net Beans (fondazione Mozilla) Intellij IDEA Sublime (70 $) Tutti gratuiti. Per sviluppare come azienda occorre però pagare i diritti. Eclipse ha plug-in per tantissimi linguaggi di programmazione Net Beans è nato per sviluppare in Java. E‟ una specie di Eclipse leggermente semplificato. IntelliJ IDEA ha sostanzialmente sostituito Net Beans. Compila java, java script, CSS, android. versione Community gratuita. Non va installato. Si scarica un pacchetto che è sufficiente unzippare. Configurazione della variabile JAVA HOME Talvolta lanciando IntelliJ IDEA, eclipse o altro, non riescono a vedere la JVM. JAVA_HOME è una variabile di sistema che tutti questi ambienti vanno a leggere per sapere dove è memorizza la JVM. Sempre su variabili d‟ambiente, però questa volta su Variabili di Sistema, creare una NUOVA variabile: nome -> JAVA_HOME valore -> C:\Program Files\Java\jdk1.7.0_45 senza \bin Le librerie base (packages) java.lang.* java.io.* Classi base (fra cui String) Classi relative all‟Input / Output pag 4 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Le basi del Linguaggio E‟ un linguaggio totalmente Object Oriented. Ogni cosa è un oggetto. Anche il main è sostanzialmente un oggetto. Qualunque programma deve iniziare con la definizione di una classe. I nomi di classe hanno di solito la prima lettera Maiuscola. Un file di classe può contenere una sola classe pubblica che deve avere lo stesso nome del file in cui è contenuta. La classe principale NON può essere statica. Nel progetto possono esistere altre classi non pubbliche scritte indifferentemente prima o dopo rispetto alla classe pubblica. Nel caso in cui il file sorgente avesse un nome diverso rispetto a quello della classe pubblica, quando si compila, il compilatore crea un file di classe scritto in BYTE CODE avente come nome quello assegnato alla classe principale. La classe pubblica deve contenere un metodo pubblico statico denominato main() che rappresenta il punto di avvio del programma. La JVM cerca ed esegue il metodo statico main (String args[]) della classe richiamata, senza istanziare la classe che può eventualmente essere istanziata all‟interno del main stesso. Per compilare il file testuale occorre richiamare il compilatore mediante il comando javac Per lanciare in esecuzione il BYTE CODE occorre lanciare la JVM mediante il comando java seguito dal nome del file di classe contenente il ByteCode L‟utility java è sostanzialmente una entry point della JVM $> edit ese01.java $> javac ese01.java $> java ese01 (scritto senza l‟estensione .class) Esercizio 1 : Input / Output da console public static void main (String[] args) { /* args.length contiene il numero di parametri */ System.out.print("Enter your name: "); String s = System.console().readLine(); System.out.println("\n Welcome " + s + " !!\n"); } La classe System.console() in genere non è disponibile quando si lavora all‟interno delle IDE, dove occorre invece utilizzare: import java.io.*; BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); String s=br.readLine(); br.readLine()legge fino al \n che NON viene incluso nel buffer. try - catch try {} catch(Exception ex) { System.out.println(ex); System.exit(1); } pag 5 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Esercizio 2 : L’oggetto Random import java.util.Random; Random rnd = new Random(); rnd.nextInt(B-A+1) + A Tipi nativi e classi base I tipi nativi char (1 byte o 2 byte se unicode ) byte (1 byte ) boolean ( 1 byte può avere valore true o false) short ( 2 byte ) ushort ( 2 byte – unsigned short) int ( 4 byte – intero) uint ( 4 byte – unsigned integer) long ( 8 byte – intero lungo) ulong ( 8 byte – unsigned long) float (4 byte – valore a precisione singola) double ( 8 byte – valore a precisione doppia) decimal ( 16 byte – valore di solito per valute) Tra i tipi nativi è possibile eseguire un semplice cast inline: int n = 97; char c = (char) n; Boxing Il termine BOXING significa racchiudere una variabile primitiva dentro un oggetto. Per ogni tipo base esiste una corrispondente classe wrapper che consente di „incapsulare‟ il tipo primitivo nel relativo wrapper, meccanismo detto appunto Boxing. Lo scopo del Boxing è quello di poter utilizzare tipi primitivi all‟interno di oggetti (come ad esempio Liste) che accettano come elementi soltanto Oggetti. La classe Wrapper ha la prima lettera maiuscola. int n = 13; Integer x = new Integer (n); Double y = new Double (5.5); Character c = new Character („x‟); Boolean b = new Boolean (true); Java 1.6 realizza il cosiddetto AutoBoxing, che consente di istanziare gli oggetti direttamente tramite assegnazione, senza dover utilizzare il new. Sostanzialmente Java 6 ridefinisce l’operatore di assegnazione facendo in modo che istanzi la classe passando al costruttore il valore dell‟assegnazione, dando vita così alla stesura di codice molto più fluido e maneggevole Integer x = 10; Double y = 5.5f; Non solo, ma anche quando si assegna un nuovo valore all‟oggetto, l‟operatore di assegnazione provvede automaticamente ad istanziare un nuovo oggetto all‟interno del quale viene „copiato‟ il valore dell‟altro oggetto, creando di fatto due oggetti indipendenti. Integer x = 10; Integer y = x; pag 6 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Unboxing Integer x = 10; int y = x; Autoboxing significa che le operazioni di Boxing e Unboxing vengono eseguite automaticamente dal compilatore del bytecode che si occupa di gestirle al posto nostro. L’operatore di Confronto Nel caso di istanze esplicite l‟operatore di confronto if(pt1 == pt2) verifica normalmente se i due puntatori stanno puntando allo stesso oggetto. Nel caso invece di istanze implicite definite mediante l‟Autoboxing, vengono confrontati non i puntatori ma il contenuto. Istanze esplicite: Integer n1 = new Integer(13); Integer n2 = new Integer(13); if(n1==n2) // false Trattandosi di due istanze esplicite indipendenti, vengono confrontati i puntatori che produrranno come esito FALSE. Autoboxing (istanze implicite): Integer n1 = 13; Integer n2 = 13; if(n1==n2) // true Questa volta, trattandosi di un autoboxing (istanze implicite) viene ridefinito anche l‟operatore == che confronta non più i puntatori ma i contenuti, producendo come esito TRUE. In C# questo problema non si pone in quanto per i wrapper numerici (così come per l‟oggetto String) l‟istanza esplicita non è consentita, quindi l‟operatore di confronto potrà agire solo su istanze implicite. L’oggetto String Il tipo String esiste solo come oggetto, quindi con la S maiuscola. Così come le classi wrapper precedenti, anche la classe String, realizza il cosiddetto AutoBoxing, con la ridefinizione dell‟operatore di assegnazione, che ogni volta reistanzia un nuovo oggetto passando al costruttore il valore dell‟assegnazione, facendo così apparire anche l‟oggetto String come un tipo nativo (scalare). String s = new String (“ciao”); // quasi equivalente a: String s = “ciao”; La stessa cosa avviene in C#, dove però c‟è anche un ulteriore alias string. Oltre all‟AutoBoxing, una ulteriore caratteristica delle stringhe, è che sono immutabili, cioè una volta istanziate non possono più essere modificate dall‟applicazione. Ogniqualvolta si tenta di assegnare un nuovo valore ad una stringa, viene automaticamente istanziata una nuova stringa ed il puntatore punterà al nuovo oggetto. La stessa cosa vale per tutte le precedenti classi wrapper, per le quali però, essendo „viste‟ quasi come variabili primitive, l‟immutabilità è molto più „naturale‟ ed intuitiva. pag 7 Tecnologie - Classe Quarta robertomana.it Introduzione a Java L‟immutabilità delle stringhe è l‟elemento fondamentale per l‟utilizzo di tecniche di hash che consentono di velocizzare ed ottimizzare le ricerche all‟interno di raccolte come Liste, Dictionary, etc La definizione della classe String è la seguente : public final class String extends Object implements Serializable, Comparable<String>, CharSequence { } la parola chiave final utilizzata davanti ad una variabile ha il significato di immutabile (costante), utilizzata davanti al nome di una classe significa cha la classe, oltre ad essere immutabile, è anche non-ereditabile. Il passaggio dei parametri Secondo una „Celebre‟ frase dello stesso Gosling, in Java i parametri possono essere passati solo per valore. I tipi primitivi possono essere passati solo per valore. Nemmeno i wrapper Integer, Double, Float, Boolean, etc. risolvono il problema in quanto, praticando l‟AutoBoxing, in corrispondenza di ogni assegnazione viene riassegnata al riferimento locale un nuovo oggetto, per cui in sostanza l‟oggetto base rimane invariato. Gli oggetti possono essere passati solo per riferimento. L'oggetto referenziato puo' essere quindi modificato dalla sottofunzione. Attenzione però che il riferimento stesso viene passato per valore, cioè viene fatta una copia del riferimento che viene ‘passata’ al chiamato attraverso lo stack. Quando una stringa (o un oggetto Integer) viene passata ad una qualunque funzione, nello stack viene passata una copia del puntatore all‟oggetto (String o Integer). Se si tenta di assegnare un nuovo valore a questo puntatore(s=”valore nuovo”, n=30), in entrambi i casi viene istanziato un nuovo oggetto ed il puntatore nello stack punterà al nuovo oggetto, Quando la funzione termina la copia del puntatore verrà rimossa dallo stack ed il puntatore del main continuerà a puntare alla vecchio oggetto. Questo può apparire scontato per gli oggetti della classe Integer (intuitivamente scalare), ma non è affatto scontato nel caso delle stringhe. Nota : Perchè le String sono dichiarate come immutabili ? Ogni volta che viene creata una stringa essa viene posta in un‟ area di memoria ben definita, chiamata “string pool” accessibile tramite hash key numerica. La hash-key numerica viene calcolata dalla funzione di hash sulla base del contenuto della stringa (come avviene ad esempio per l‟MD5) e restituita al chiamante. Prima di inserire una stringa nel pool, la JVM effettua una ricerca hash per verificare se è già presente lo stesso valore letterale, che viene restituito senza essere replicato, altrimenti calcola e restituisce la corrispondente hash key numerica. Modificando la stringa cambierebbe la hash key numerica ed il meccanismo cadrebbe. Dopo di che all‟interno delle varie cache viene memorizzata non la stringa ma il suo codice hash numerico. L'hashing è alla base della ricerca indicizzata tramite chiave utilizzata in tutti i DB. Una ricerca basata su hashing è completamente diversa da una basata su confronti: invece di muoversi nella struttura data in funzione dell'esito dei confronti tra chiavi, si cerca di accedere agli elementi nella tabella in modo diretto tramite operazioni aritmetiche che trasformano le chiavi in indirizzi della tabella. Esistono vari tipi di algoritmi di hashing. In una tabella di hashing ben dimensionata il costo medio di ricerca di ogni elemento è indipendente dal numero di elementi. pag 8 Tecnologie - Classe Quarta robertomana.it Introduzione a Java L'hashing è un problema classico dell'informatica; molti algoritmi sono stati proposti, studiati a fondo e impiegati in pratica. ll primo passo per realizzare algoritmi di ricerca tramite hashing è quello di determinare la funzione di hash: il dato da indicizzare viene trasformato da un'apposita funzione di hash in un numero intero compreso tra 0 ed m-1 che viene utilizzato come indice in una tabella (hash table) T [ 0 .. m-1 ] di lunghezza m. La funzione di hash in pratica stabilisce una corrispondenza tra l‟universo delle chiavi e le posizioni nella tabella hash. Idealmente, chiavi diverse dovrebbero essere trasformate in indirizzi differenti, ma poiché non esiste la funzione di hash perfetta, (ovvero totalmente iniettiva), è possibile che due o più chiavi diverse siano convertite nello stesso indirizzo. Il caso in cui la funzione hash applicata a due chiavi diverse genera un medesimo indirizzo viene chiamato collisione e può essere gestito in vari modi. La scelta di una buona funzione di hash è indispensabile per ridurre al minimo le collisioni e garantire prestazioni sempre ottimali. Il risultato migliore si ha con funzioni pseudo-casuali che distribuiscono i dati in input in modo uniforme. Molto spesso però, una buona funzione di hash può non bastare: infatti le prestazioni di una hash table sono fortemente legate anche al fattore di carico (load factor) calcolato come Celle libere / Elementi presenti e che indica la probabilità che ha un nuovo elemento di collidere con uno già presente nella tabella. Il load factor deve essere il più basso possibile (di solito un valore di 0.75 è quello ottimale) per ridurre al minimo il numero di collisioni. Ciò può essere fatto ad es ridimensionando l'array ogni volta che si supera il load factor desiderato (come fa automaticamente l‟oggetto List sia in Java che in C#) Principali metodi dell’oggetto String s.length(); s.toUpperCase(); s.toLowerCase(); Il metodo s1.equals(s2) o equalsIgnoreCase(s2) servono per confrontare il contenuto di due istanze esplicite ritornando true se uguali (deep equals, opposto allo shallow equals di ==) . Il metodo (s1.compareTo(s2) == 0) identico al precedente s = s.concat(String str) Concatena la sottostringa in coda alla stringa principale. Come + char c= s.charAt(int pos) Restituisce il carattere alla posizione indicata. b = s.contains(String str) Restituisce true se la stringa contiene la sottostring indicata. int pos = s.indexOf(String str, int fromIndex) Il primo parametro può essere un int che rappresenta il codice ascii di un carattere. int pos = s.lastIndexOf(String str, int fromIndex) s = s.substring(int beginIndex, int endIndex) Restituisce la sottostringa indicata (con endIndex escluso) String[] parts = s.split("-"); b = s.matches(String regex) Indica se la stringa fa match con la Regular Expression La conversione fra i tipi Ognuna delle classi wrapper dei tipi base presenta dei metodi statici per la conversione del valore (contenuto all‟interno della classe) da e verso stringa int n= Integer.parseInt(s); String s=Integer.toString(n); String s=String.valueOf(n); Double x = Double.parseDouble(s); Double x = Double.valueOf(n); Boolean b = Boolean.parseBoolean("true"); s=Boolean.toString(b); pag 9 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Es: double double double double x x x x = = = = 0; // ERRORE 0.0; // OK Double.parseDouble(“0”); Double.valueOf(0); L’istruzione switch E‟ identica all‟ANSI C. Può agire SOLO su variabili numeriche o singoli caratteri. Il risultato dello switch viene confrontato con ogni etichetta e il prg esegue un salto all‟etichetta corrispondente, dopo di che l‟intero codice successivo viene eseguito fino a quando non si incontra un eventuale break. Dopo l‟ultimo case (o il default) il break può essere omesso Dopo la chiusa graffa dello switch occorre un punto e virgola Vettori I Vettori sono classi „normali‟ a tutti gli effetti. Come tutti gli oggetti essi sono: Trattati per referenza Istanziabili solo tramite new I vettori possono essere dichiarati in diversi modi int myArray []; int [] myArray; int [] myArray = new int [10]; E' possibile inizializzare i vettori in uno dei seguenti modi int [] myArray = { 1, 3 , 5, 6}; int [] myArray = new int [] { 1, 3 , 5, 6}; myArray.length => numero degli elementi del vettore. La lunghezza di un vettore, una volta creato, non puo' essere piu' cambiata. Se serve un vettore che possa crescere o decrescere dinamicamente, bisogna usare l'oggetto ArrayList Matrici Un vettore bidimensionale(o in generale multidimensionale) viene definito come un vettore di vettori: int mat[][] = new int[2][5] ; Si possono avere anche righe di lunghezza differente: int mat [][] = { {1, 3, 4},{2,4},{5}}; mat.length => 3 (numero di righe) mat [0].length => 3 - mat [1].length => 2 - mat [2].length => 1 Ellissi Se si passano ad un metodo più parametri tutti dello stesso tipo [ES sum (5,7,9,11)], il metodo può usare la sintassi detta ellipsis che consente di trattare i vari parametri come se appartenessero tutti ad un unico vettore: int sum (int ... n) { for (int i = 0; i < n.length; i++) totale += n[i]; return totale; pag 10 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Le strutture Java non ha il tipo struct. Al suo posto si può usare una classe con sole proprietà pubbliche. Le liste Le Liste in Java, come in C #, sono Typed Object, cioè occorre definire il tipo. ArrayList<String> listaCitta = new ArrayList<String>(); for (int i = 0; i < 100; i++) listaCitta.add(“item”+); for (int i = 0; i < listaCitta.size(); i++) toast(listaCitta.get(i); Nota List è una interfaccia,e dunque non può essere istanziata direttamente, ma può ad esempio essere restituita da un metodo che esegue il cast da ArrayList. ArrayList viceversa è una classe che implementa l‟interfaccia List e dunque può essere istanziata. Ci sono anche altre classi che implementano l‟interfaccia List in modo diverso da ArrayList, ad es la classe LinkedList I cicli Sono identici all‟ANSI C con la possibilità di break e continue. Esiste anche il ciclo for each che presenta la seguente sintassi : String [] stringhe = { “stringa1”, “stringa2” }; for (String s : stringhe) visualizza(s) Gestione delle Eccezioni Qualunque istruzione che può generare errore DEVE essere racchiusa in un TRY – CATCH. Il catch riceve come parametro un oggetto e (error) che presenta i seguenti metodi: e.getMessage() e.getCause() e.printStackTrace() restituisce il messaggio interno puntatore all‟oggetto causa (cioè in sostanza oggetto e genitore, se questo è stato passato come secondo parametro del throw) visualizza il messaggio nello stackTrace In alternativa un metodo che possa sollevare eccezioni, può essere scritto senza TRY – CATCH con la sintassi : public void myMethod() throws Exception { } Se il metodo intende invece risollevare esplicitamente una eccezione all‟interno del catch, la sintassi è la seguente : throw new Exception("valore non valido", e); Il chiamante riceve un oggetto Exception, in cui getMessage() restituisce l‟ultimo errore, mentre getCause() può accedere all‟oggetto Exception precedente. Se lo desidera, il chiamante può fare una procedura ricorsiva per accedere, tramite e.getCause() successivi, a tutta la catena degli errori. Se il throw NON passa come secondo parametro l‟errore precedente, il metodo getCause() restituirà undefined. pag 11 Tecnologie - Classe Quarta robertomana.it Introduzione a Java I Files di testo L’oggetto File contiene tutte le informazioni relative al file passato come parametro al costruttore. File myFile = new File(”file.txt”) Sull’oggetto File sono disponibili i seguenti metodi: getPath, isFile, isDirectory, exists, delete, rename In realtà lettura / scrittura sul file possono essere eseguiti anche senza passare attraverso l‟oggetto File, ma partendo direttamente dal path. Lettura di un file import java.io.*; FileReader reader = new FileReader("file.txt"); BufferedReader br = new BufferedReader(reader); String s, testo; while((s=br.readLine()) != null) testo += s + “\n”; br.close(); reader.close(); Il metodo .readLine() legge una intera riga senza però restituire il \n finale che deve (eventualmente) essere aggiunto manualmente. Scrittura su un file L‟intero file costituito eventualmente anche da righe multiple può essere salvato in un colpo solo tramite il metodo .write(). FileWriter writer; writer = new FileWriter(“file.txt”, true); // writer = new FileWriter(“file.txt”, false); writer.write("Lorem Ipsum\r\n"); writer.flush(); writer.close(); // append // overwrite, default Per vedere se un file esiste ed è effettivamente un file e non una directory: File myFile = new File(path); if(myFile.isFile()) FileReader reader = new FileReader(myFile); else myFile.createNewFile(); Per leggere il contenuto di una cartella : File dir = new File(path); String [] vect = dir.list(); I Packages Rappresentano un meccanismo per organizzare le classi. Consentono ad esempio di creare classi pubbliche con nomi uguali. E‟ sufficiente inserirle all‟interno di package differenti. Al di fuori delle parole chiave del linguaggio e dei tipi nativi, tutto il resto è memorizzato all‟interno dei package. Tutte le classi principali sono raccolte all‟interno del package java.lang. pag 12 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Eclipse Quando si crea un nuovo progetto, viene creato un nuovo package con il nome del progetto all‟interno del quale saranno posizionate tutte le classi appartenenti al progetto. Da un punto di vista del file system, il package corrisponde ad una cartella (avente lo stesso nome del package) all‟interno della quale verranno posizionati tutti i file relativi alle classi contenute nel package. E‟ possibile comunque in Eclipse rinomare il progetto (e quindi la cartella) senza che venga rinominato il package. Il file .classpath mantiene le necessarie corrispondenze. Il Garbage Collector ll garbage collector è un meccanismo che tiene traccia delle locazioni di memoria utilizzate e le libera solo quando non sono più necessarie. Java non permette al programmatore di accedere ad una qualsiasi locazione di memoria come avviene in C/C++. In Java non esistono puntatori con le stesse caratteristiche di quelli del C/C++. I puntatori in Java sono solo riferimenti impliciti ad oggetti allocati dinamicamente su uno heap e distrutti attraverso il meccanismo automatico di garbage collection. Il metodo finalize(), se presente all‟interno della classe, viene automaticamente richiamato dal garbage collector un attimo prima di deistanziare l‟oggetto. Può servire per eseguire operazioni di pulizia come ad esempio la chiusura di files eventualmente aperti o la disconnessione di connessioni di rete. Le Classi Le Proprietà rappresentano lo stato dell‟oggetto. Tendenzialmente devono essere sempre private. Il loro accesso può essere effettuato solo attraverso i metodi propertyGet() e propertySet(). Quindi in sostanza di una classe dall‟esterno si vedono SOLO i metodi (incapsulamento !). Le property con GET e SET automatiche esistono SOLO in Dot.Net I Metodi descrivono invece il comportamento dell‟oggetto, cioè le operazioni che l’oggetto sarà in grado di eseguire. Ad esempio animale1.corri(); Un metodo statico è un metodo che dipende dalla classe e non dall‟istanza. Le variabili interne ai metodi (compresi i parametri) sono dette variabili automatiche nel senso che, al termine, vengono automaticamente deallocate. Classi statiche In Java ogni classe può avere dei membri statici, ma non esiste il concetto di classe statica. Una classe deve sempre essere istanziata Qualificatori di Visibilità di Proprietà e Metodi private package protected public Visibile solo all‟interno della classe default (da omettere). Visibile in tutte le classi interne al package (internal di C#) come package ma Ereditato nelle sottoclassi Visibile da tutti pag 13 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Qualificatori di Visibilità di una classe Sono gli stessi di cui sopra: private Visibile soltanto all‟interno della classe nella quale è stata dichiarata. package default (da omettere). Visibile da tutte le classi interne al package (internal di C#) protected come package ma Ereditato nelle sottoclassi public Visibile da tutti Una classe può essere anche abstract (must Inherits) o final (not inheritable, sealed in C#) Ogni file di classe può contenere una sola classe pubblica che deve avere lo stesso nome del file. Il costruttore Il valore di ritorno di un costruttore non può in nessun modo essere letto. Per questo si omette void, in quanto in realtà non può essere diversamente. Tra l‟altro il costruttore sarebbe anche static (viene richiamato quando l‟istanza ancora non esiste). All‟interno di una classe A è anche possibile dichiarare un metodo public void A() { } che diventa un normale metodo che però NON E‟ PIU‟ UN COSTRUTTORE. La parola chiave this usata all‟interno di una classe rappresenta un riferimento all‟istanza. Quando si accede ad un membro di classe con nome univoco (cioè quando non c‟è ambiguità) this può essere omesso. E‟ invece obbligatorio ad esempio all‟interno di un metodo che usa una vriabile locale con lo stesso nome. Un costruttore può richiamare un altro costruttore mediante la sintassi : this(par1, par2) Variabili Reference (riferimenti) Animale cane; cane è semplice riferimento non inizializzato. cane = new Animale(); viene istanziato un nuovo cane ed inizializzato il riferimento. Il termine pointer (puntatore) si usa nel caso di normali variabili native. Il termine handler (maniglia o riferimento) si usa per gli oggetti Esempio class A { private int x; public A() { x=3; } public void incrementa() { x++; } } class B { public B() { } public void incrementa(A a){ a.incrementa(); } } // riferimento alla classe a MAIN A a = new A(); a.incrementa(); // x diventa 4 B b = new B(); b.incrementa(a); // x diventa 5 pag 14 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Ereditarietà Per ereditare una classe da un‟altra si utilizza l‟istruzione extends class Macchina2 extends Macchina{ private int costoKm; public Macchina2 ( ) { super(“fiat”, 600); costoKm=10; } public int calcolaSpesa(){ return costoKm*getKm(); } } Quando istanziamo macchina2 in realtà istanziamo anche una normale macchina per cui la sottoclasse Macchina2 deve in qualche modo richiamare il costruttore della classe da cui eredita passandogli i parametri necessari. La PRIMA riga del costruttore di macchina2 deve necessariamente richiamare come PRIMA istruzione, mediante la parola chiave super(),il costruttore della superclasse passandogli i parametri necessari. Overload e Override In Java è possibile eseguire implicitamente sia l‟overloading sia l‟overriding dei metodi senza nessuna dichiarazione aggiuntiva. Poer quanto riguarda l‟override è possibile anteporre al nuovo metodo la notazione @Override che è una annotazione aggiunta, facoltativa, da anteporre al metodo che esegue l‟override, per indicare al compilatore che il metodo su cui è posta sta effettuando unoverride di un metodo della sua superclasse. Lo scopo è quello di evitare errori. Se si crede di fare un override di un metodo che però nella classe base non dovesse esistere (con quella firma), il compilatore segnala un errore. Metodi di override inline In Java è possibile definire un metodo “al volo” in fase di creazione dell‟istanza. Macchina my = new Macchina("fiat", 700) { void visualizza () { System.out.println("Metodo disponibile per la sola istanza my"); } }; Il problema è che il nuovo metodo non può in alcun modo essere richiamato. Con questa tecnica è però possibile eseguire un override temporaneo di un metodo esistente. Nel caso dell‟override il metodo risulta richiamabile in quanto è già appartenente alla classe base. In corrispondenza del richiamo viene però richiamato il nuovo metodo definito inline. pag 15 Tecnologie - Classe Quarta robertomana.it Introduzione a Java La libreria grafica java-SWING Le librerie grafiche di base di Java sono le librerie AWT ( Abstract Window Toolkit ) contenenti tutte le classi e le interfacce fondamentali per la creazione di elementi grafici. AWT è stata inserita nelle API standard di Java per lo sviluppo di applicazioni GUI in modo veloce ed efficiente. In realtà le AWT sono abbastanza complicate da utilizzare. Sono allora state create altre librerie dette SWING che sono sostanzialmente un wrapper semplificato delle librerie AWT. Gerarchia delle classi della libreria java.swing pag 16 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Elementi Base di Java Swing Visualizzazione di una MessageBox import javax.swing.*; JOptionPane.showMessageDialog(null, "Messaggio di esempio"); Firma completa: Object showInputDialog(Component parent, Object Message, String title, int messageType, Icon icon, Object[] SelectedValues, Object initialValue) Il parametro parent serve a specificare il frame principale; esso verrà bloccato fino al termine dell'interazione. Ponendo a null questo parametro la finestra verrà visualizzata al centro dello schermo e risulterà indipendente dal resto dell'applicazione. La classe Color this.setBackground(Color.cyan); Il beep toolkit.beep(); Terminazione dell’applicazione System.exit(0); pag 17 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Istanza di una nuova form import java.awt.*; import javax.swing.*; import java.awt.event.* Una nuova form può essere creata in due modi: a) tramite una classe che eredita direttamente da JFrame (che è l‟equivalente della Windows Form) public class Form1 extends JFrame JPanel pnl = new JPanel(); JButton btn1 = new JButton(); JButton btn2 = new JButton(); { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { Form1 frm = new Form1 (); } }); } Proprietà e Metodi della form saranno accessibili come this.xxxxx b) tramite una classe ‘normale’ che dichiara ed istanzia un oggetto JFrame public class mainClass { JFrame form1 = new JFrame(); JPanel pnl = new JPanel(); JButton btn1 = new JButton(); JButton btn2 = new JButton(); public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { mainClass frm = new mainClass (); } }); } Proprietà e Metodi della form saranno accessibili come form1.xxxxx In entrambi i casi: Il metodo statico main( ) funge da metodo Factory e provvede a creare una nuova istanza della classe base. Poiché il metodo statico main( ) si limita ad istanziare la classe, il riferimento frm viene perso non appena il main() termina, però la classe pubblica rimane istanziata ed in esecuzione come una nuova Form. Per cui è‟ anche possibile (preferibile) non dichiarare il riferimento e scrivere soltanto new Form1(); pag 18 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Thread separati Una nuova Form viene di solito istanziata all'interno di un THREAD separato in modo che il processo principale possa continuare ad interagire con l‟utente („sentire‟ il mouse, etc.). I Thread in Java sono rappresentati mediante un oggetto chiamato Runnable. invokeLater() è un metodo statico della classe SwingUtilities che consente di eseguire un nuovo thread all‟interno del quale è possibile eseguire la creazione del thread stesso. All‟interno di invokeLater il programmatore deve semplicemente eseguire l‟override del metodo run : public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { mainClass frm = new mainClass(); } }); } Inizializzazione della form all’interno del costruttore Le principali inizializzazioni da eseguire su una form, da eseguirsi tipicamente all‟interno del costruttore della classe, sono le seguenti: public Form1(){ form1.setSize(300, 200); form1.setLocation(300, 300); form1.setTitle("Form1"); form1.setLocationRelativeTo(null); form1.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); form1.setVisible(true); } } setSize definisce le dimensioni della form (larghezza e altezza) setLocation definisce la posizione x y di visualizzazione della form (spigolo in alto a sinistra) setVisible rende la form visible (di default è invisibile). setTitle definisce il contenuto della barra del titolo setLocationRelativeTo se sull‟oggetto corrente sono state definite il setSize o il setBounds, questo metodo consente di posizionare l‟oggetto rispetto ad un oggetto contenitore passato come parametro. Passando come valore null l‟oggetto viene posizionato a centro video (ma SOLO se a monte sono stati fatti il setSize o il setBounds). Questa riga ovviamente „copre‟ l‟impostazione effettuata da setLocation(). setDefaultCloseOperation fa sì che la chiusura della form (con click sulla x in alto a destra) comporti automaticamente anche la chiusura dell‟intera applicazione, compresa la JVM che altrimenti rimarrebbe in esecuzione. Centratura della Form sullo schermo tramite la classe Toolkit import java.awt.*; // java.awt.Toolkit e java.awt.Dimension; Toolkit toolkit = this.getToolkit(); Dimension size = toolkit.getScreenSize(); this.setLocation((size.width - this.getWidth())/2, (size.height - this.getHeight())/2); pag 19 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Inserimento dei controlli all’interno della Form In Swing non si possono aggiungere nuovi controlli direttamente all‟interno del JFrame, ma controlli e Panel possono essere inseriti soltanto all‟interno del Container che rappresenta l‟area Client della Form. Questo Container rappresenta sostanzialmente un Panel a cui si può accedere mediante il metodo this.getContentPane(); Su qualunque Panel (compreso il Container) si può disegnare (forme, immagini...) oppure si possono aggiungere controlli esistenti esattamente come in C#. JPanel panel = new JPanel(); Container c = f.getContentPane(); c.add(pnl); oppure, dal momento che il Container è esso stesso un Panel : Container pnl = this.getContentPane(); Il metodo pnl.setLayout(null); consente di poter eseguire un posizionamento manuale assoluto dei controlli all‟interno del Panel stesso, ad esempio attraverso il metodo setBounds, disponibile per tutti i controlli e che consente di definire posizione e dimensioni del controllo. btn.setBounds(50, 60, 80, 30); // x, y, width, height Il metodo pnl.setLayout(new FlowLayout(FlowLayout.CENTER)); imposta come layout il FlowLayout, che è il default di tutti i Panel tradizionali ma non è il default del Container base. Il metodo pnl.setLayout(new GridLayout(nRighe, nColonne)); imposta una griglia. Il tipo di layout da assegnare ad un Panel, oltre che tramite il metodo set Layout(), può essere impostato anche passando il riferimento direttamente al costruttore: Panel pnl = new JPanel(new GridLayout(3,1)); Pannello Principale Il pannello principale utilizza come default un GridBagLayout abbastanza complicato. Questo Layout così come il GridLayout semplice consente una espansione automatica dei controlli in corrispondenza dell‟espansione della Form. Pannelli interni Utilizzano come default il il FlowLayout. Se anche si applica questi pannelli il GridLayout ma il pannello principale non è di tipo GridLayout, l‟espansione automatica dei controlli non avviene. Aggiunta di nuovi controlli all’interno di un Panel JLabel lbl=new JLabel("Etichetta"); pnl.add(lbl); Per ogni controllo, è sempre possibile passare al costruttore il VALUE del controllo stesso. Il metodo frm.pack(); Se dopo aver aggiunto i controlli sulla form si richiama il metodo frm.pack(), esso ridimensiona la form in modo da contenere esattamente i controlli inseriti, ciascuno con la propria dimensione. pag 20 Tecnologie - Classe Quarta robertomana.it Introduzione a Java La gestione degli eventi Ad eccezione di JLabel, tutti gli altri componenti Java generano molti eventi differenti. Anche gli eventi in Java sono degli oggetti, istanza della classe generica java.util.EventObject oppure di una sottoclasse più specifica. Ad esempio il pulsante JButton , quando premuto, genera un evento di classe ActionEvent. Quando si genera un qualsiasi evento, il RunTime istanzia una classe Event contenente tutte le informazioni sull‟evento (ad es chi generato l‟evento) ed „invia‟ tale oggetto ad un ascoltatore degli eventi (Listener) che deve essere stato preventivamente associato a quel controllo. L‟ascoltatore degli eventi deve implementare una adeguata interfaccia strettamente legata al tipo di evento. Nel caso di un ActionEvent (tipicamente il click ma anche il tasto INVIO su un TextBox) occorre associare un ActionListener il quale deve implementare il metodo void actionPerformed(ActionEvent e); definito all‟interno dell‟interfaccia stessa e che viene automaticamente eseguito in corrispondenza del verificarsi di un ActionEvent relativo al controllo. L‟associazione dell‟ ActionListener al controllo può essere eseguita in almeno tre modi diversi : 1) Definizione di un Listener locale associato al singolo controllo Nel momento in cui si aggiunge il Listener al controllo si può istanziare in loco una nuova classe specifica per quel controllo. btn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.exit(0); } }); La precedente rappresenta sostanzialmente una singola istruzione, la quale dovrà essere inserita all‟interno di una procedura (tipicamente al termine di InizializeComponent()). Questo approccio chiaramente non va bene nel caso in cui si desidera associare una medesima procedura di evento a più pulsanti. 2) Definizione di un Listener generico associabile a più controlli btn.addActionListener( new myListener()); class myListener implements ActionListener { @Override public void actionPerformed(ActionEvent e){ System.exit(0); } } Questa tecnica è probabilmente la migliore e più flessibile. Per ogni controllo associato occorre creare una nuova apposita istanza del Listener. pag 21 Tecnologie - Classe Quarta robertomana.it Introduzione a Java 3) Impostazione della Form (o del Panel) come Listener per gli eventi di tutti i controlli. E‟ infine anche possibile delegare la Form (o il Panel) ad implementerà lei l‟interfaccia ActionListener, nel qual caso la Form stessa al suo interno dovrà contenere l‟override del metodo actionPerformed. Nel momento in cui si dichiara il gestore di eventi di un qualsiasi controllo, occorre indicare la Form stessa come classe Listener. btn.addActionListener(this); Tutti gli eventi relativi a tutti i controlli potranno essere gestiti all‟interno della medesima procedura actionPerformed : public class Form1 extends JFrame implements ActionListener ……………………………………………………………………………………………………………… ……………………………………………………………………………………………………………… @Override public void actionPerformed(ActionEvent e){ System.exit(0); } } { Individuazione dell’evento specifico Nel caso in cui più controlli eseguano la stessa procedura di evento, è possibile individuare il sender utilizzando il metodo e.getSorce() che restituisce un RIFERIMENTO al controllo che ha scatenato l‟evento. if (e.getSource() == btn1) { } Il metodo e.getActionCommand() restituisce invece il value del sender. if (e.getActionCommand() == “rosso”) { } I principali tipi di evento ActionListener WindowListener MouseListener MouseMotionListener FocusListener ItemListener TextListener KeyListener pag 22 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Gli eventi relativi alla Form (WindowEvent) Gli eventi relativi alla Form sono dichiarati all‟interno dell‟interfaccia WindowListener, che normalmente viene implementata dalla form stessa, utilizzando la precedente Terza Forma di associazione. L‟interfaccia WindowListener definisce i seguenti metodi astratti: public public public public public public public void void void void void void void windowActivated(WindowEvent e); windowDeactivated(WindowEvent e); windowOpened(WindowEvent e); windowClosed(WindowEvent e); windowClosing(WindowEvent e); windowIconified(WindowEvent e); windowDeiconified(WindowEvent e); Iconified significa finestra ridotta ad icona. Dentro windowClosing si può impostare System.exit(0); che forza la chiusura dell‟intera applicazione in modo esattamente analogo rispetto al metodo form1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Notare che nel momento in cui si implementa questa interfaccia, TUTTI i metodi astratti in essa contenuti dovranno essere implementati dall‟applicazione. Questi metodi possono essere scritti : direttamente all‟interno della Main Class, nel qual caso occorrerà che la classe implementi l‟interfaccia WindowListener e occorrerà poi scrivere : this.addWindowListener(this); che significa: la form corrente utilizza se stessa come classe di ascolto degli eventi. All‟interno di una classe secondaria che implementi Lei l‟interfaccia WindowListener esattamente come nel caso degli Action Listener. In questo caso occorrerà poi scrivere : this.addWindowListener(form_events); La gestione del layout Il gestore predefinito per un pannello è FlowLayout, che dispone i componenti in modo affiancato uno di fianco all'altro da sinistra verso destra e va a capo se non ci stanno tutti su una riga. I Controlli sono allineati sia verticalmente che orizzontalmente al centro della form. I possbili layout applicabili ad un Panel sono i seguenti : FLowLayout, default pnl.setLayout(new FlowLayout(FlowLayout.LEFT)); Definisce un FlowLayout allineato a sinistra. I possibili valori sono LEFT, CENTER, RIGHT. Il default è CENTER. BorderLayout, Dispone i componenti lungo i bordi o al centro pnl.setLayout(new BorderLayout()); Definisce un BorderLayout in cui per ogni Controllo si può specificare un ancoraggio in modo simile rispetto alla Proprietà Dock di C#. I valori possibili sono North, South, Center, East, Weast pnl.add(ctrl,"South"); Controllo ancorato al lato inferiore della form. GridLayout, Ddispone i componenti in una griglia m × n pnl.setLayout(new GridLayout(nRighe, nColonne, spO, spV)); Gli ultimi due parametri (opzionali) rappresentano la spaziatura orizzontale e verticale tra le celle. I controlli sono posizionati in base all'ordine con cui vengono aggiunti. pag 23 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Il valore GridLayout fa sì che i controlli vengano automaticamente ingranditi in seguito all‟eventuale resizing della form. GridBagLayout, che dispone i componenti in una griglia m × n flessibile. Consente di gestire righe e colonne a dimensione variabile; molto flessibile e potente, ma più complesso dei precedenti BoxLayout, che dispone i componenti o in orizzontale o in verticale, in un'unica casella (layout predefinito per il componente Box) nessun layout manager (null). Si specifica la posizione assoluta (x,y) del componente. pnl.setLayout(null) ; consente di poter eseguire un posizionamento manuale dei controlli ad esempio attraverso il metodo setBounds che, applicato ad un controllo, consente di definire posizione e dimensioni E‟ ovviamente possibile definire più layout manager annidati uno dentro l‟altro. Esempi pag 24 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Proprietà e Metodi comuni ai principali Controlli .setName(String); imposta il nome del controllo .setText(String); imposta il value del controllo .setSize(300, 200); dimensione del controllo .setLocation(300, 300); posizione del controllo .setBounds(50, 60, 80, 30); posizione e dimensione : x, y, width, height .setBackground(Color); imposta il colore di sfondo .setEditable(bool); imposta il controllo come editabile / non editabile .requestFocus(); sposta il focus sul controllo attuale .setFont(new Font("Courier", Font.BOLD, 20)); Per allineare un testo a destra lblN1.setHorizontalAlignment(SwingConstants.RIGHT); setSize() e setPreferredSize() I metodi setSize( ) e setLocation( ) sono riconosciuti SOLTANTO dai controlli che sono inseriti all‟interno di un Parent che non utilizza nessun tipo di LayoutManager (setLayout(null)). Vanno bene pertanto anche per i componenti top level (ad esempio il JFrame principale) che di fatto non hanno un Parent. Viceversa non sono riconosciuti dai controlli inseriti all‟interno di un Panel che utilizzi un qualsiasi Layout Manager: In questo caso infatti il Layout Manager provvede a posizionare e ridimensionare automaticamente i controlli sulla base del tipo di Layout e sulla base del contenuto. Ad esempio nel caso del FlowLayout i TextBox privi di contenuto avranno larghezza 0, mentre ad esempio nel caso del GridLayout i Text Box, anche se vuoti, assumono la larghezza della colonna. Per quanto riguarda il Size() sono disponibili tre metodi alternativi utilizzabili per i controlli inseriti all‟interno di Parent dotati di LayoutManager : setMinimumSize( ) dimensione minima del controllo che può però essere aumentata in base alle esigenze del LayoutManager setMaximumSize( ) dimensione massima del controllo che può però essere diminuita in base alle esigenze del LayoutManager setPreferredSize( ) dimensione preferenziale del controllo che può però essere modificata in base alle esigenze del LayoutManager Esempio: .setPreferredSize(new Dimension(100, 20)); JTextField Quando si preme il tasto INVIO sul TextBox viene generato un ActionEvent analogo a quello dei pulsanti Per intercettare invece le variazione del testo occorre assegnare al controllo un DocumentListener: pag 25 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Eventi :L‟interfaccia da implementare è DocumentListener txt1.getDocument().addDocumentListener(this); class myListener implements DocumentListener { public void insertUpdate(DocumentEvent e){ txt2.setText(txt1.getText()); } public void removeUpdate(DocumentEvent e){ txt2.setText(txt1.getText()); } public void changedUpdate(DocumentEvent e){} txt2.setText(txt1.getText()); } } JTextArea JTextArea myTextArea=new JTextArea("Esempio di textArea"); myTextArea.setSize(150, 150); myTextArea.setText(“nuovo testo”); // sovrascrive testo esistente myTextArea.append(“nuovo testo”); // aggiunge in coda append aggiunge il testo in coda ma senza andare a capo. Per fare una nuova riga occorre inserire un \n in testa (o in coda alla precedente). In alternativa a setSize(), qualora il controllo si trovi all‟intero di un Parent dotato di LayoutManager, si possono utilizzare setRows(10) e setColumns(40) cioè numero di righe e numero di colonne che costituiscono la TextArea. Per numero di colonne si intende il numero max di caratteri per riga, calcolati sulla base di un certo tipo di Font monospace. JCheckBox Il checked è verificabile con isSelected()e attivabile da codice con setSelected(true) Eventi :Ogni volta che lo stato della casella cambia viene generato un ActionEvent analogo a quello dei pulsanti ed anche un ItemEvent più specifico. In caso di più caselle gestite dallo stesso listener, il metodo e.getItemSelectable() restituisce un riferimento all'oggetto sorgente dell'evento JRadioButton Per rendere alternativi i RadioButton occorre definire un ButtonGroup che è un oggetto indipendente rispetto ai Panel. Ogni singolo radio button deve essere aggiunto sia al Panel che serve per la visualizzazione grafica sia al ButtonGroup che serve per renderli alternativi. ButtonGroup grp = new ButtonGroup(); grp.add(rdbF); grp.add(rdbM); Il checked è verificabile con isSelected() e attivabile da codice con setSelected(true) Inizialmente i Radio Buttons sono tutti deselezionati. Dopo che una Option è stata selezionata non c‟è più modo di ritornare in una situazione con tutte le Option disabilitate. In sostanza il setSelected(false) non sortisce nessun effetto. La documentazione Java relativa alla classe ButtonGroup fornisce il seguente suggerimento : To give the appearance of "none selected", add an invisible radio button to the group and then programmatically select that button to turn off all the displayed radio buttons. Da Java 6 in Avanti è stato aggiunto il comodissimo metodo buttonGroup.clearSelection() pag 26 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Eventi : Quando si cambia la casella selezionata, si generano tre eventi : un ItemEvent per la casella deselezionata, uno per la casella selezionata, e un ActionEvent da parte della casella selezionata (evento preferibile) JComboBox private JComboBox <String> cmbColori = new JComboBox <String>(); Per configurare l'elenco delle voci proposte, si usa il metodo addItem() Per recuperare la voce scelta o scritta, si usa getSelectedItem() Eventi : Quando si sceglie una voce o se ne scrive una nuova, si genera un ActionEvent JList Per configurare l'elenco delle voci proposte, non è disponibile il metodo addItem() ma sono disponibili due differenti strategie: String voci[]={"Cuneo", "Torino", "Fossano", "Savigliano"}; lstCitta = new JList(voci); DefaultListModel listaCitta = new DefaultListModel(); listaCitta.addElement("Cuneo"); listaCitta.addElement("Saluzzo"); listaCitta.addElement("Fossano"); lstCitta.setModel(listaCitta); pnl.add(lstCitta); Per recuperare la/e voce/i selezionate si usano getSelectedValue() e getSelectedValues() Per selezionare una voce da codice si può utilizzare setSelectedValue(“valore”, true) oppure setSelectedIndex(int index). E‟ possibile associare alla Lista una Scroll Bar utilizzando il seguente Panel: JScrollPane lstPanel = new JScrollPane(lstCitta); pnl.add(lstPanel); setSize() e setLocation() dovranno essere impostate non più su lstCitta ma su lstPanel Eventi : Quando si sceglie una voce si genera un evento ListSelectionEvent, gestito da un ListSelectionListener. Il listener deve implementare il metodo void valueChanged(ListSelectionEvent) pag 27 Tecnologie - Classe Quarta robertomana.it Introduzione a Java Le finestre di dialogo Per poter utilizzare le finestre di dialogo relative ai files (typ FileOpen e FIleSave), occorre dichiarare ed istanziare un oggetto di tipo JFileChooser private JFileChooser dlg = new JFileChooser(); L‟oggetto JFileChooser dispone dei metodi di istanza showOpenDialog() e showSaveDialog() che sono identici con la sola differenza della riga del titolo e che consentono rispettivamente di aprire una finestra di dialogo di tipo Open ed una tipo Save. Entrambe queste finestre si aspettano come parametro un Component parent rispetto al quale eseguire il posizionamento della nuova finestra di dialogo. Inoltre, impostando il parent, se la finestra principale viene ridotta d icona, anche la Dialog (nel caso in cui non sia bloccante) viene ridotta ad icona, per ricomparire automaticamente nel momento in cui in cui la finestra principale ritorna visibile. Come Component parent si utilizza solitamente Form1.this, E‟ anche possibile utilizzare il valore null nel qual caso la Finestra di Dialogo viene centrata rispetto allo schermo e non ha collegamenti con la finestra principale. Metodi di JFileChooser : dlg.getSelectedFile()) restituisce come oggetto File il percorso assoluto del file selezionato dall‟utente. private File myFolder = new File("F:/myFolder"); dlg.setCurrentDirectory(myFolder); Cartella su cui si apre la finestra di Dialogo. In alternativa questo parametro può essere passato al costruttore di JFileChooser dlg.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) consente all‟utente di poter selezionare soltanto Cartelle. Il default è FILES_ONLY E‟ anche utilizzare il valore FILES_AND_DIRECTORIES FileNameExtensionFilter filter = new FileNameExtensionFilter( ".txt and .java files", "txt", "java"); chooser.setFileFilter(filter); consente di impostare un filtro sulle estensioni dei files da visualizzare all‟interno della dialog Proprietà di showOpenDialog e showSaveDialog Il metodo dlg.showSaveDialog() restituisce un intero che rappresenta il codice del pulsante utilizzato dall‟utente per chiudere la finestra di dialogo: int returnVal = dlg.showOpenDialog(null); if (returnVal == JFileChooser.APPROVE_OPTION) { pag 28