Προγραµµατισµός ΙΙ Ηγλώσσααντικειµενοστραφούς προγραµµατισµού Java ιδάσκων ηµήτριος Κατσαρός, Ph.D. @ Τµ. Μηχανικών Η/Υ, Τηλεπικοινωνιών & ικτύων Πανεπιστήµιο Θεσσαλίας ιάλεξη 9η: 24/05/2006 & 25/05/2006 1
α) Θέτοντας ιδιότητες του προγράµµατος β) Προσπελάζοντας τους πόρους του συστήµατος Setting Program Attributes Accessing System Resources 2
ΗκλάσηProperties Τα προγράµµατα σε Java εκτελούνται σε ένα περιβάλλον που χαρακτηρίζεται από τις ιδιότητες του συστήµατος (system attributes) host machine, χρήστη, τρέχον directory, λειτουργικό σύστηµα Τα προγράµµατα σε Java µπορούν επίσης να θέσουν τις δικές τους τροποποιήσιµες ιδιότητες, που αποκαλούνται ιδιότητες του προγράµµατος (program attributes) Τα system attributes διατηρούνται στην κλάση System Τα Java προγράµµατα µπορούν να τα θέσουν µε τρεις µηχανισµούς: properties command-line arguments applet parameters (ότι τα command-line arguments, αλλά για applets) 3
ΗκλάσηProperties Μια ιδιότητα αποτελείται από δυο τµήµατα: το όνοµα (name) και την τιµή (value) του, π.χ., os.name είναι το όνοµα γιαένα από τα system attributes της πλατφόρµας της Java. Η τιµήτου περιέχει το όνοµα του τρέχοντος λειτουργικού συστήµατος, όπως π.χ., Solaris ΗκλάσηSystem χρησιµοποιεί ένα αντικείµενο Properties για να διαχειρίζεται τα system properties. Κάθε πρόγραµµα Java µπορεί να χρησιµοποιεί ένα αντικείµενο Properties για να διαχειρίζεται τα program attributes. Η κλάσηproperties παρέχει µεθόδους για τα ακόλουθα: Φόρτωση ζευγών key/value σε ένα αντικείµενο Properties από ένα ρεύµα (stream) Ανάκτηση µιας τιµής µε βάση το αντίστοιχο key Παράθεση των keys και των values Απαρίθµηση όλων των keys Αποθήκευση των ιδιοτήτων σε ένα ρεύµα (stream) 4
ΗκλάσηProperties ΗκλάσηProperties επεκτείνει (extends) την κλάση HashtableProperties και κληρονοµεί από αυτή µεθόδους για να εκτελεί τα ακόλουθα: Έλεγχο εάν ένα key ή value ανήκει στο αντικείµενο Properties Ανάκτηση του τρέχοντος αριθµού των ζευγών key/value ιαγραφή ενός key και της value του Προσθήκη ενός ζεύγους key/value στη λίστα του Properties Απαρίθµηση πάνω στα values ήσταkeys Ανάκτηση µιας value µεβάσητοkey Έλεγχο εάν το αντικείµενο Properties είναι κενό 5
Ο κύκλος ζωής των Ιδιοτήτων Προγράµµατος Loads default properties from wellknown default location Loads values from last invocation from well-known location Starting up Initializes itself based on default and remembered properties Sets or modifies various properties based on user interaction Running Saves values to well-known location for next time Exiting 6
Φτιάχνοντας το δικό µας αντικείµενο Properties Ο επόµενος κώδικας εκτελεί τα δυο πρώτα βήµατα: // create and load default properties Properties defaultprops = new Properties(); FileInputStream in = new FileInputStream("defaultProperties"); defaultprops.load(in); in.close(); // create program properties with default Properties applicationprops = new Properties(defaultProps); // now load properties from last invocation in = new FileInputStream("appProperties"); applicationprops.load(in); in.close(); 7
Αποθηκεύοντας το αντικείµενο Properties Το επόµενο παράδειγµα γράφει τις properties της εφαρµογής χρησιµοποιώντας τη µέθοδο save του αντικειµένου Properties. Οι default properties δεν χρειάζεται να αποθηκεύονται κάθε φορά, επειδή δεν τροποποιούνται FileOutputStream out = new FileOutputStream("appProperties"); applicationprops.save(out, "---No Comment---"); out.close(); Η µέθοδος save χρειάζεται ένα stream γιαναγράψει, όπως και ένα string που το χρησιµοποιεί ως σχόλιο στην κορυφή της εξόδου 8
Ανακτώντας πληροφορίες από το Properties Μέθοδοι για ανάκτηση πληροφορίας από το Properties: contains(object value) containskey(object key) Επιστρέφει true εάν η value ή τοkey υπάρχει στο αντικείµενο Properties. Το Properties κληρονοµεί αυτές τις µεθόδους από το Hashtable. Εποµένως, δέχονται ορίσµατα τύπου Object. Πρέπει να περνάµε Strings getproperty(string key) getproperty(string key, String default) Επιστρέφει τη value της καθοριζόµενης property. Η δεύτερη έκδοση µας επιτρέπει να καθορίσουµε µια default value. Εάν το key δεν βρεθεί, επιστρέφεται η default 9
Ανακτώντας πληροφορίες από το Properties Μέθοδοι για ανάκτηση πληροφορίας από το Properties: list(printstream s) list(printwriter w) Γράφει όλες τις properties στο καθοριζόµενο stream ή writer. Είναι χρήσιµο για αποσφαλµάτωση elements() keys() propertynames() Επιστρέφει ένα Enumeration που περιέχει τα keys ή values (όπως φανερώνεται από το όνοµα τηςµεθόδου) που περιέχονται στο αντικείµενο Properties size() Επιστρέφει τον τρέχοντα αριθµό των ζευγών key/value 10
Θέτοντας πληροφορία στο Properties Η αλληλεπίδραση ενός χρήστη µεέναπρόγραµµα κατά τη διάρκεια εκτέλεσής του µπορεί να επηρεάσει τις τιµές των property. Αυτές οι αλλαγές πρέπει να αντικατοπτρίζονται στο αντικείµενο Properties, έτσι ώστε να αποθηκεύονται όταν τερµατιστεί το πρόγραµµα (και καλέσει τη µέθοδο save). Μπορούµεναχρησιµοποιήσουµε τις ακόλουθες µεθόδους για να αλλάξουµε τις ιδιότητες του αντικειµένου Properties: put(object key, Object value) Θέτει το ζεύγος key/value στο αντικείµενο Properties remove(object key) ιαγράφει το ζεύγος key/value που σχετίζεται µετοkey 11
Ορίσµατα γραµµής εντολής Μια εφαρµογή Java µπορείναδεχτείοποιονδήποτε αριθµόορισµάτων από τη γραµµήεντολής java Sort friends.txt Όταν ενεργοποιούµε µια εφαρµογή Java, το σύστηµα εκτέλεσης περνάει τα ορίσµατα γραµµής εντολής (command-line arguments) στη µέθοδο main της εφαρµογής ως ένας πίνακας από Strings. Κάθε String του πίνακα περιέχει ένα από τα ορίσµατα της γραµµής εντολής. Στο προηγούµενο παράδειγµα, τα command-line arguments που περνιούνται στην εφαρµογή Sort είναι ένας πίνακας που περιέχει µόνο το String: "friends.txt" 12
Ορίσµατα γραµµής εντολής Εάν το πρόγραµµά µας χρειάζεται ένα αριθµητικό όρισµα γραµµής εντολής, πρέπει να µετατρέψει το όρισµα String, που αναπαριστά αυτόν τον αριθµό, στο αριθµητικό του ισοδύναµο Το παρακάτω παράδειγµα µετατρέπει ένα command-line argument σε έναν int: int firstarg; if (args.length > 0) firstarg = Integer.parseInt(args[0]); η parseint πετάει µια εξαίρεση NumberFormatException εάν η µορφή του args[0] δεν είναι έγκυρη. Όλες οι αριθµητικές κλάσεις, δηλ., Integer, Float, Double, κ.τ.λ., έχουν τις µεθόδους parsexxx που µετατρέπουν ένα String που αναπαριστά έναν αριθµό σεαντικείµενο του τύπου τους 13
Προσπέλαση στους πόρους συστήµατος Κάθε πρόγραµµα χρειάζεται προσπέλαση στους πόρους του συστήµατος, όπως είναι οι ιδιότητες του συστήµατος, η standard είσοδος και έξοδος Το πρόγραµµά µας θα µπορούσε να κάνει άµεσα system calls κατευθείαν στο λειτουργικό σύστηµα, αλλά τότε θα µπορούσε να εκτελεστεί µόνο στο συγκεκριµένο περιβάλλον Η Java platform µας επιτρέπει να προσπελάσουµε τους πόρους του συστήµατος διαµέσου ενός (σχετικά) ανεξάρτητου-από-το-σύστηµα API που υλοποιείται από την κλάση System και διαµέσου ενός εξαρτηµένου-από-το-σύστηµα API που υλοποιείται από την κλάση Runtime 14
Χρήση της κλάσης System O παρακάτω κώδικας δείχνει τη χρήση της κλάσης System class UserNameTest{ public static void main(string[] args) { String name; name = System.getProperty("user.name"); System.out.println(name); } } ιαφορετικά από άλλες κλάσεις, δεν αρχικοποιούµε την κλάση System, πριν τη χρησιµοποιήσουµε Γιαναείµαστε ακριβείς, ΕΝ ΜΠΟΡΟΥΜΕ να αρχικοποιήσουµε τηνsystem, επειδή είναι final κλάση και όλοι οι constructors της είναι private. 15
Τα standard I/O ρεύµατα Έχουµε ήδη δει σε παλιότερη διάλεξη τα standard ρεύµατα: Standard input -- System.in Standard output -- System.out Standard error -- System.err Ανακατεύθυνση των ρευµάτων αυτών µε: setin(inputstream in) seterr(printstream err) setout(printstream out) 16
System Properties ΗκλάσηSystem διατηρεί ένα σύνολο ιδιοτήτων, δηλ., ζευγών key/value, που καθορίζουν χαρακτηριστικά του τρέχοντος περιβάλλοντος εργασίας. Όταν το σύστηµα εκτέλεσης ξεκινά, οι system properties αρχικοποιούνται ώστε να περιέχουν πληροφορία για το περιβάλλον εκτέλεσης, που περιλαµβάνει πληροφορίες για τον τρέχοντα χρήστη, την τρέχουσα έκδοση της Java, γιατονχαρακτήραπου χρησιµοποιείται ως διαχωριστικό για τις συνιστώσες των ονοµάτων αρχείων Ο πίνακας της επόµενης διαφάνειας παρουσιάζει µια πλήρη λίστα των system properties που έχουµε όταν ξεκινά το runtime system: 17
System Properties 18
ιαβάζοντας τα System Properties ΗκλάσηSystem έχει δυο µεθόδους που µπορούµε να χρησιµοποιήσουµε για να διαβάσουµε ταsystem properties: getproperty getproperties Επιστρέφει ένα αντικείµενο Properties που περιέχει το πλήρες σύνολο των ζευγών key/value για το system property. Μπορούµε ναχρησιµοποιήσουµε τιςµεθόδους της κλάσης Properties για να ρωτήσουµε τααντικείµενα Properties για συγκεκριµένες τιµές ή για να πάρουµε όλο το σύνολο των properties 19
Θέτοντας τα System Properties (1/5) Μπορούµε να τροποποιήσουµετουπάρχον σύνολο των system properties µε χρήσητης µεθόδου setproperties της κλάσης System. Αυτή η µέθοδος δέχεται ένα αντικείµενο Properties που έχει αρχικοποιηθεί να περιέχει τα ζεύγη key/value για τις ιδιότητες που επιθυµούµε. ηλ., η µέθοδος αυτή αντικαθιστά ολόκληρο το σύνολο των system properties µε ένανέο σύνολο που αναπαρίσταται από το αντικείµενο Properties 20
Θέτοντας τα System Properties (2/5) import java.io.fileinputstream; import java.util.properties; public class PropertiesTest { public static void main(string[] args) throws Exception { // set up new properties object // from file "myproperties.txt" FileInputStream propfile = new FileInputStream( "myproperties.txt"); Properties p = new Properties(System.getProperties()); p.load(propfile); } } // set the system properties System.setProperties(p); // display new properties System.getProperties().list(System.out); 21
Θέτοντας τα System Properties (3/5) Παρατηρήστε πώς το προηγούµενο πρόγραµµα δηµιουργεί το αντικείµενο p τύπου Properties, το οποίο χρησιµοποιείται ως όρισµαστηµέθοδο setproperties: Properties p = new Properties(System.getProperties()); Αυτή η δήλωση αρχικοποιεί το νέο αντικείµενο ιδιοτήτων pµετοτρέχονσύνολοτωνproperties (στο συγκεκριµένο µικρό παράδειγµα είναι το σύνολο των properties που αρχικοποιήθηκαν από το σύστηµα εκτέλεσης). Κατόπιν το πρόγραµµαφορτώνειεπιπλέονιδιότητες στο p απότοαρχείοmyproperties.txt και θέτει τις system properties ίσο µετοp 22
Θέτοντας τα System Properties (4/5) Σηµειώστε ότι µπορείτε να δηµιουργήσετε το p χωρίς κάποιο default αντικείµενο Properties, µε τονεξής τρόπο: Properties p = new Properties(); Εάν το κάνετε αυτό, τότε η εφαρµογή σας δεν θα έχει πρόσβαση στις system properties. Επίσης, σηµειώστε ότι η τιµήτωνsystem properties µπορεί να γίνει overwritten! Για παράδειγµα, εάν το myproperties.txt περιέχει την ακόλουθη γραµµή, η system property java.vendor θα γίνει overwritten: java.vendor= Acme Software Company Γενικά, αποφύγετε να κάνετε overwrite των system properties 23
Θέτοντας τα System Properties (5/5) Η µέθοδος setproperties αλλάζει το σύνολο των system properties µόνο για την τρέχουσα εφαρµογή Αυτές οι αλλαγές δεν είναι µόνιµες, δηλ., αλλάζοντας τις σε µια εφαρµογή δεν θα επηρεάσει τις µελλοντικές ενεργοποιήσεις του Java interpreter για την εφαρµογή αυτήήάλλες. Το σύστηµα εκτέλεσης αρχικοποιεί ξανά τις system properties κάθε φορά που ξεκινά Εάν επιθυµούµε οι αλλαγές µας στις system properties να είναι µόνιµες, τότε η εφαρµογή µας θα πρέπει να γράφει τις τιµές σε αρχείο πριν τερµατιστεί και να τις φορτώνει ξανά όταν ξεκινά 24
Finalization και Garbage Collection Το σύστηµα εκτέλεσης της Java εκτελεί από µόνο του της διαχείριση της µνήµης και δεν την αφήνει στον προγραµµατιστή, όπως η C/C++ µετιςfree/delete Όταν το πρόγραµµά µας δεν πρόκειται να χρησιµοποιήσει ξανά κάποιο αντικείµενο, δηλ., όταν δεν υπάρχουν άλλες αναφορές (references) στο αντικείµενο αυτό, τότε το αντικείµενο λέµε ότι finalized και συλλέγεται ως σκουπίδι (garbage collected). Αυτές οι λειτουργίες συµβαίνουν ασύγχρονα στο υπόβαθρο Όµως, µπορούµεναεπιβάλουµε τηνfinalization και την garbage collection χρησιµοποιώντας κατάλληλες µεθόδους της κλάσης System 25
Finalizing τα αντικείµενα Πριν κάποιο αντικείµενο γίνει garbage collected, η Java δίνει στο αντικείµενο µια ευκαιρία να καθαρίσει τον εαυτό του. Αυτό το βήµα είναι γνωστό ως finalization και επιτυγχάνεται µε µια κλήση στη µέθοδο finalize του αντικειµένου Το αντικείµενο θα πρέπει να κάνει override τη µέθοδο finalize για να εκτελέσει το τελικό καθάρισµα, όπως είναι η απελευθέρωση πόρων του συστήµατος (αρχεία και sockets) Μπορούµε να επιβάλλουµε την ενεργοποίηση της finalization των αντικειµένων µετηνκλήσητηςµεθόδου runfinalization System.runFinalization(); Αυτή η µέθοδος, καλεί τις µεθόδους finalize όλων των αντικειµένων που αναµένουν να γίνουν garbage collected. Μπορούµε επίσης τους finalizers να εκτελεστούν πριν τερµατιστεί η εφαρµογή Java, µε κλήσητηςµεθόδου: System.runFinalizersOnExit(true) 26
Εκτελώντας τον Garbage Collector Μπορούµε ναζητήσουµε απότονgarbage collector να εκτελεστεί όποια στιγµή επιθυµούµε µε κλήσητηςµεθόδου του συστήµατος gc: System.gc(); Το πρόγραµµά µας µπορεί να επιθυµεί να εκτελέσει τον garbage collector λίγο πριν ξεκινήσει ένα compute ή memory intensive τµήµα του κώδικά µας ή όταν γνωρίζει ότι υπάρχει ένα idle σηµείο του κώδικα Σηµειώστε ότι η εκτέλεση του garbage collector απαιτεί σηµαντικό χρόνο. Τοποσότουχρόνουεξαρτάταιαπό διάφορους παράγοντες: Πόσο µεγάλος είναι ο σωρός (heap) Πόσο γρήγορος είναι ο επεξεργαστής Ο garbage collector θα πρέπει να εκτελείται όταν δεν θα έχει επίδραση στην επίδοση του προγράµµατός µας 27
ιαχείριση ασφάλειας (Security managers) Ηασφάλεια(security) είναι µέγιστης σηµασίας όταν γράφουµεκαιχρησιµοποιούµε προγράµµατα που αλληλεπιδρούνε µετονinternet Ένας από τους τρόπους που η Java χρησιµοποιεί για να παρέχει προστασία από επιθέσεις είναι η χρήση των διαχειριστών ασφαλείας (security managers) Ένας security manager υλοποιεί και εφαρµόζει µιας πολιτική ασφαλείας για µια εφαρµογή Ο security manager είναι ένα application-wide αντικείµενο που προσδιορίζει κατά πόσο εν δυνάµει επικίνδυνες λειτουργίες θα πρέπει να επιτραπούν. Οι κλάσεις στα Java packages συνεργάζονται µε τον security manager της εφαρµογής ζητώντας από αυτόν άδεια για να εκτελέσουν κάποιες λειτουργίες 28
Εισαγωγή στον Security Manager (1/4) Κάθε Java εφαρµογή µπορείναέχειτοδικότης αντικείµενο σε ρόλο security manager που λειτουργεί ως φρουρός ασφαλείας ΗκλάσηSecurityManager που βρίσκεται στο πακέτο java.lang είναι µια abstract class που παρέχει το interface και µερική υλοποίηση για όλους τους security managers της Java Εξ ορισµού µια εφαρµογή δεν έχει security manager, δηλ., το σύστηµα εκτέλεσης της Java runtime δεν δηµιουργεί αυτόµατα έναν security manager για κάθε εφαρµογή. Έτσι, εξ ορισµού κάθε εφαρµογή επιτρέπει όλες τις λειτουργίες που υπόκεινται σε περιορισµούς ασφαλείας Γιανααλλάξουµε αυτήτηνεξ ορισµού συµπεριφορά, µια εφαρµογή πρέπει να δηµιουργήσει και να εγκαταστήσει το δικό της security manager. 29
Εισαγωγή στον Security Manager (2/4) Μπορούµε ναπάρουµε τον τρέχοντα security manager για µια εφαρµογή µε χρήσητηςµεθόδου getsecuritymanager() της κλάσης System: SecurityManager appsm = System.getSecurityManager(); Η getsecuritymanager() επιστρέφει null εάν δεν υπάρχει τρέχων security manager για την εφαρµογή Κατόπιν, µπορούµε να ζητήσουµε άδεια για να επιτραπεί ή αποτραπεί κάποια λειτουργία. Πράγµατι, πολλές από τις κλάσεις των Java packages το κάνουν αυτό. Για παράδειγµα, η µέθοδος System.exit(), που τερµατίζει τον Java interpreter, χρησιµοποιεί τη µέθοδο checkexit() του security manager για να εγκρίνει τη λειτουργία exit: SecurityManager security = System.getSecurityManager(); if (security!= null) { security.checkexit(status); }... // code continues here if checkedexit() returns 30
Εισαγωγή στον Security Manager (3/4) Εάν ο security εγκρίνει την exit, η checkexit() επιστρέφει κανονικά. Εάν ο security manager δεν την εγκρίνει, η checkexit() πετάει µια εξαίρεση SecurityException ΗκλάσηSecurityManager ορίζει πολλές άλλες µεθόδους που χρησιµοποιούνται για να επαληθεύουν άλλες λειτουργίες Για παράδειγµα, η µέθοδος checkaccess() του SecurityManager επαληθεύει πρόσβαση των thread, και η checkpropertyaccess() επαληθεύει πρόσβαση στην καθοριζόµενη ιδιότητα. Κάθε λειτουργία ή οµάδα λειτουργιών έχει τη δική της µέθοδο checkxxx() 31
Εισαγωγή στον Security Manager (4/4) Το σύνολο των µεθόδων checkxxx() αναπαριστά το σύνολο των λειτουργιών πάνω στις κλάσεις των Java package και του Java runtime, που υπόκεινται σε προστασία από τον security manager. Έτσι, τυπικά, ο κώδικας που γράφουµε δεν χρειάζεται να περιέχει ρητή κλήση σε κάποια από τις µεθόδους checkxxx() της κλάσης SecurityManager οι κλάσεις των Java package και το Java runtime το κάνουν ήδη αυτό σε αρκετά χαµηλό επίπεδο, έτσι ώστε κάθε λειτουργία που αναπαρίσταται από µια µέθοδο checkxxx() είναι ήδη προστατευόµενη Όµως, όταν γράφουµε τους δικούς µας security manager, ίσως χρειαστεί να κάνουµε override κάποιες από τις µεθόδους checkxxx(), ώστε να σφίξουµε ή να τροποποιήσουµε την πολιτική ασφάλειας για συγκεκριµένες λειτουργίες ή ίσως χρειαστεί να προσθέσουµε µερικές νέες για να βάλουµε άλλα είδη περιορισµών κάτω από την εποπτεία του security manager 32
Γράφοντας τον Security Manager (1/8) Γιαναγράψουµε τονδικόµας security manager, πρέπει να δηµιουργήσουµε µια υποκλάση της κλάσης SecurityManager. Η υποκλάση αυτή κάνει overrides διάφορες µεθόδους της αρχικής κλάσης SecurityManager για να προσαρµόσουµε τις επαληθεύσεις και επιβεβαιώσεις που απαιτεί η εφαρµογή µας Στα επόµενα παρουσιάζουµε ένα παράδειγµα security manager που περιορίζει την ανάγνωση και εγγραφή στο σύστηµα αρχείων. Γιαναπάρουµε έγκρισηαπότονsecurity manager, µια µέθοδο που ανοίγει ένα αρχείο για ανάγνωση, ενεργοποιεί µια από τις µεθόδους checkread(). Όµοια, µια µέθοδος που ανοίγει ένα αρχείο για εγγραφή, ενεργοποιεί µια από τις µεθόδους checkwrite(). Εάν ο security manager εγκρίνει τη λειτουργία, η µέθοδος checkxxx() επιστρέφει, αλλιώς πετάει µια εξαίρεση SecurityException 33
Γράφοντας τον Security Manager (2/8) Γιαναεφαρµόσουµε αυστηρότερη πολιτική, η υποκλάση της SecurityManager που φτιάχνουµε πρέπει να κάνει override τις µεθόδους checkread() και checkwrite() Ο SecurityManager παρέχει τρεις νέες εκδόσεις για την checkread() και δυο νέες εκδόσεις για την checkwrite(). Κάθε µια από αυτές πρέπει να επιβεβαιώνει ότι η λειτουργία επιτρέπεται. Η πολιτική που υλοποιείται στο παράδειγµά µας προτρέπει τον χρήστη να δώσει ένα password όταν η εφαρµογή επιχειρεί να ανοίξει ένα αρχείο για ανάγνωση ή για εγγραφή. Εάν το password είναι το σωστό, η πρόσβαση επιτρέπεται 34
Γράφοντας τον Security Manager (3/8) Όλοι οι security managers πρέπει να είναι υποκλάσεις της SecurityManager class PasswordSecurityManager extends SecurityManager {... } Κατόπιν, ο PasswordSecurityManager δηλώνει µια private instance variable password γιαναπεριέχειτοpassword που θα εισαγάγει ο χρήστης, ώστε να του επιτραπεί πρόσβαση στο σύστηµα αρχείων. Το password τίθεται µε τηνκατασκευή: PasswordSecurityManager(String password) { super(); this.password = password; } Η επόµενη µέθοδος της κλάσης PasswordSecurityManager είναι µια private βοηθητική µε όνοµα accessok(). Ζητάει από τον χρήστη το password και το επαληθεύει. Εάν είναι το σωστό, επιστρέφει true; αλλιώς επιστρέφει false. 35
Γράφοντας τον Security Manager (4/8) private boolean accessok() { int c; DataInputStream dis = new DataInputStream(System.in); String response; System.out.println("What's the secret password?"); try { response = dis.readline(); if (response.equals(password)) return true; else return false; } catch (IOException e) { return false; } } 36
Γράφοντας τον Security Manager (5/8) Τελικά, στο τέλος της κλάσης PasswordSecurityManager είναι οι τρεις overridden checkread() µέθοδοι και οι δυο overridden checkwrite() µέθοδοι: 37
Γράφοντας τον Security Manager (6/8) public void checkread(filedescriptor filedescriptor) { if (!accessok()) throw new SecurityException("Not a Chance!"); } public void checkread(string filename) { if (!accessok()) throw new SecurityException("No Way!"); } public void checkread(string filename, Object executioncontext) { if (!accessok()) throw new SecurityException("Forget It!"); } public void checkwrite(filedescriptor filedescriptor) { if (!accessok()) throw new SecurityException("Not!"); } public void checkwrite(string filename) { if (!accessok()) throw new SecurityException("Not Even!"); } 38
Γράφοντας τον Security Manager (7/8) Όλες οι checkxxx() καλούν την accessok() για να ζητήσουν το password. ΕάνηπρόσβασηδενείναιOK, τότε οι checkxxx() πετάνε µια SecurityException. Αλλιώς, οι checkxxx() επιστέφουν κανονικά Η SecurityException είναι runtime exception, και συνεπώς δεν χρειάζεται να δηλωθεί στην throws πρόταση των µεθόδων Μπορούµε νακάνουµε override όσες και όποιες checkxxx() µεθόδους επιθυµούµε, ώστε να υλοποιήσουµε τηδικήµας πολιτική ασφάλειας. εν χρειάζεται να κάνουµε override όλες τις checkxxx() Όµως, ηεξ ορισµού υλοποίηση που παρέχεται από την κλάση SecurityManager για όλες τις checkxxx() πετάει µια SecurityException. Με άλλα λόγια, εξ ορισµού η SecurityManager αποτρέπει κάθε λειτουργία που υπόκειται σε περιορισµούς ασφαλείας 39
Γράφοντας τον Security Manager (8/8) Όλες οι checkxxx() µέθοδοι της SecurityManager λειτουργούν όµοια: Εάν επιτρέπεται η πρόσβαση, η µέθοδος επιστρέφει Εάν δεν επιτρέπεται η πρόσβαση, πετάγεται µια SecurityException Πρέπει να υλοποιούµε τις overridden checkxxx() µεθόδους µε τον ίδιο τρόπο ΗυλοποίησηενόςSecurityManager είναι απλή. Πρέπει: Να δηµιουργήσουµε µια υποκλάσης της SecurityManager Να κάνουµε override µερικές µεθόδους Το δύσκολο είναι να αποφασίσουµε ποιεςµεθόδους να κάνουµε override και να υλοποιήσουµε τηνπολιτική ασφάλειας 40
Εγκατάσταση του Security Manager (1/4) Αφού γράψουµε τηδικήµας υποκλάση της SecurityManager, µπορούµε να την εγκαταστήσουµε ως τον τρέχοντα security manager για την εφαρµογή µας. Αυτό γίνεται µετηµέθοδο setsecuritymanager() της κλάσης System Στα επόµενα φτιάχνουµε µια µικρή εφαρµογή, που εγκαθιστά την κλάση PasswordSecurityManager ως τον τρέχοντα security manager. Κατόπιν, για να επιβεβαιώσουµε ότι λειτουργεί κανονικά, η εφαρµογή ανοίγει δυο αρχεία ένα για ανάγνωση και το άλλο για εγγραφή και αντιγράφουµε ταπεριεχόµενα του πρώτου στο δεύτερο αρχείο Η main() αρχίζει µε την εγκατάσταση ενός νέου security manager: try { System.setSecurityManager(new PasswordSecurityManager("Booga Booga")); } catch (SecurityException se) { System.out.println("SecurityManager already set!"); } 41
Εγκατάσταση του Security Manager (2/4) Η κόκκινη γραµµήστοπροηγούµενο κοµµάτι κώδικα δηµιουργεί ένα νέο στιγµιότυπο της κλάσης PasswordSecurityManager µε τοpassword "Booga Booga". Αυτό το στιγµιότυπο περνάει στη µέθοδο setsecuritymanager(), ηοποίαεγκαθιστάτο αντικείµενοαυτόωςτοντρέχονταsecurity manager για την εκτελούµενη εφαρµογή. Αυτός ο security manager θα παραµείνει σε λειτουργία κατά τη διάρκεια εκτέλεσης της εφαρµογής Μπορούµεναθέσουµε τονsecurity manager της εφαρµογής µας µόνο µια φορά, δηλ., µπορούµε να ενεργοποιήσουµε τηνsystem.setsecuritymanager() µόνο µια φορά. Οποιαδήποτε απόπειρα να εγκαταστήσουµεέναννέοsecurity manager µέσα στην εφαρµογή θα προκαλέσει SecurityException 42
Εγκατάσταση του Security Manager (3/4) try { DataInputStream fis = new DataInputStream( new FileInputStream("inputtext.txt")); DataOutputStream fos = new DataOutputStream( new FileOutputStream("outputtext.txt")); String inputstring; while ((inputstring = fis.readline())!= null) { fos.writebytes(inputstring); fos.writebyte('\n'); } fis.close(); fos.close(); } catch (IOException ioe) { System.err.println("I/O failed."); } 43
Εγκατάσταση του Security Manager (4/4) Οι κόκκινες γραµµές στον προηγούµενο κώδικα είναι ελεγχόµενες προσβάσεις στο σύστηµα αρχείων Αυτές οι κλήσεις των µεθόδων έχουν ως συνέπεια µια κλήση στη µέθοδο checkaccess() της PasswordSecurityManager 44
Αποφασίζοντας ποιες µεθόδους του SecurityManager να κάνουµε override Ίσως χρειαστεί να κάνουµε override αρκετές από τις µεθόδους checkxxx(), ανάλογα µε τις λειτουργίες στις οποίες θέλουµεοsecurity manager να επιβάλει περιορισµούς Ηπρώτηστήλητωνπινάκωνστιςεπόµενες δυο διαφάνειες είναι τα αντικείµενα πάνω στα οποία εκτελούνται διάφορες λειτουργίες. Ηδεύτερηστήλη παραθέτει τις µεθόδους της κλάσης SecurityManager που εγκρίνουν τις λειτουργίες πάνω στα αντικείµενα της πρώτης στήλης 45
Αποφασίζοντας ποιες µεθόδους του SecurityManager να κάνουµε override 46
Αποφασίζοντας ποιες µεθόδους του SecurityManager να κάνουµε override 47
Αποφασίζοντας ποιες µεθόδους του SecurityManager να κάνουµε override Ανάλογα µε την πολιτική ασφάλειας που επιθυµούµε, µπορούµε να κάνουµε override µερικές ή όλες τις µεθόδους Πολλές από τις checkxxx() καλούνται σε πολλαπλές καταστάσεις, για το λόγο αυτό πρέπει να κατανοούµε σεποιες περιστάσεις µπορεί να κληθεί Ηεξ ορισµού υλοποίηση που παρέχεται από την κλάση SecurityManager για όλες τις µεθόδους checkxxx() είναι η ακόλουθη: public void checkxxx(...) { throw new SecurityException(); } Οι περισσότερες από τις πολιτικές µας για την ασφάλεια θα είναι πιο επιλεκτικές από το να αποτρέψουν όλες τις λειτουργίες. Έτσι, ίσως χρειαστεί να κάνουµε override όλες τις µεθόδους checkxxx() της κλάσης SecurityManager 48
Το αντικείµενο Runtime 49
Το αντικείµενο Runtime Στην καρδιά του συστήµατος εκτέλεσης της Java βρίσκεται η Java virtual machine, ο Java interpreter, και το φιλοξενούν λειτουργικό σύστηµα Ηέλλειψηµε ετικέτα Runtime στο διάγραµµατης προηγούµενης διαφάνειας αναπαριστά το τρέχον σύστηµα εκτέλεσης και είναι ένα στιγµιότυπο (instance) της κλάσης Runtime Το τρέχον σύστηµα εκτέλεσης θα µπορούσε να είναι οτιδήποτε, π.χ., µια υλοποίηση από την Sun της Java virtual machine και ο interpreter που εκτελείται σε Solaris ή η υλοποίηση από την ACME Company της virtual machine και ο interpreter που εκτελείται στην ACME ψηστιέρα 50
Το αντικείµενο Runtime Τα αντικείµενα Runtime παρέχουν δυο υπηρεσίες. Πρώτον, επικοινωνούν µε τις συνιστώσες του συστήµατος εκτέλεσης λαµβάνοντας πληροφορίες και ενεργοποιώντας συναρτήσεις. εύτερον, τα αντικείµενα Runtime παρέχουν τη διασύνδεση µε ικανότητες εξαρτώµενες από το σύστηµα (system-dependent capabilities) Π.χ., τα αντικείµενα Runtime σε UNIX πιθανόν να υποστηρίζουν τις λειτουργίες getenv και setenv. Τα αντίστοιχα Runtime αντικείµενα σε Mac OS, ίσως τις υποστηρίζουν Επειδή η κλάση Runtime είναι σφιχτά ενσωµατωµένη µε τη υλοποίηση του Java interpreter, της Java virtual machine, και του υποκείµενου λειτουργικού συστήµατος, είναι εξαρτηµένη απότοσύστηµα. Γενικά, δεν είναι καλή ιδέα να τη χρησιµοποιούµε (ειδικά για τα applets). 51
ιασύνδεση µε χρήστη: Swing I Creating User Interfaces: Swing I 52
Εισαγωγή στο Swing Το Java package AWT (Abstract Window Toolkit) είναι το αρχικό Java package για το σχεδιασµό της Αλληλεπίδρασης µε τοχρήστη(gui) Ένα GUI (graphical user interface) είναι ένα παραθυρικό σύστηµα που αλληλεπιδρά µε τοχρήστη Το package Swing είναι µια βελτιωµένη έκδοση του AWT Όµως, δεν αντικαθιστά πλήρως το AWT Μερικές AWT κλάσεις αντικαθίστανται από Swing κλάσεις, αλλά κάποιες άλλες του AWT απαιτούνται όταν χρησιµοποιούµε το Swing Τα Swing GUIs σχεδιάζονται χρησιµοποιώντας µιας µορφή του αντικειµενοστραφούς προγραµµατισµού που καλείται προγραµµατισµός µε γεγονότα (event-driven programming) 53
Γεγονότα - Events Event-driven programming είναι το προγραµµατιστικό στυλ που χρησιµοποιεί την προσέγγιση σήµα-και-απάντηση (signal-and-response) στον προγραµµατισµό Ένα γεγονός (event) είναι ένα αντικείµενο που ενεργεί ως σήµα σε ένα άλλο αντικείµενο, το οποίο καλείται ο ακουστής (listener) Η αποστολή ενός event καλείται ενεργοποίηση του event (firing the event) Το αντικείµενο που ενεργοποιεί το event είναι συχνά µια συνιστώσα GUI, όπως ένα κουµπί το οποίο έχει γίνει clicked 54
Listeners Ένα αντικείµενο-listener object εκτελεί κάποια ενέργεια σε απάντηση στο event Μια δεδοµένη συνιστώσα µπορεί να έχει οποιοδήποτε αριθµό απόlisteners Κάθε listener µπορεί να αποκρίνεται σε ένα διαφορετικό είδος event, ή πολλαπλοί listeners µπορεί να αποκρίνονται στα ίδια events 55
Αντικείµενα Εξαιρέσεις (Exception Objects) Ένα exception object είναι ένα event Το πέταµα µιας εξαίρεσης είναι ένα παράδειγµα ενεργοποίησης ενός event Ο listener για ένα exception object είναι το µπλοκ catch που πιάνει το event 56
ιαχειριστές Γεγονότων - Event Handlers Ένα αντικείµενο listener έχει µεθόδους που καθορίζουν τι θα συµβεί όταν λάβει διαφόρων τύπων events Αυτές οι µέθοδοι καλούνται διαχειριστές γεγονότων (event handlers) Οπρογραµµατιστής που χρησιµοποιεί το αντικείµενο listener θα ορίσει ή θα ξανα-ορίσει αυτούς τους event-handler 57
Event Firing και Event Listener 58
Event-driven προγραµµατισµός Οπρογραµµατισµός µε γεγονότα(event-driven programming) είναι πολύ διαφορετικός από τον προγραµµατισµός που έχουµεδειµέχρι τώρα Μέχρι τώρα, τα προγράµµατα αποτελούνταν από µια λίστα δηλώσεων που εκτελούνταν µε τη σειρά Όταν η σειρά άλλαζε, ώστε να εκτελέσει ή όχι κάποιες λειτουργίες (όπως επαναλαµβανόµενες δηλώσεις σε ένα βρόχο, κλάδος σε άλλη δήλωση, ή ενεργοποίηση µιας µεθόδου) ελεγχόταναπότηλογικήτου προγράµµατος 59
Event-driven προγραµµατισµός Στον event-driven προγραµµατισµό, δηµιουργούνται αντικείµενα που µπορεί να ενεργοποιήσουν events, και επίσης δηµιουργούνται αντικείµενα listener που µπορούν να αντιδράσουν στα events Το πρόγραµµα πλέον δεν προσδιορίζει τη σειρά µε τηνοποίασυµβαίνουν τα πράγµατα Αλλά, τα events καθορίζουν τη σειρά 60
Event-driven προγραµµατισµός Σε ένα event-driven πρόγραµµα, το επόµενο πράγµαπουθασυµβείεξαρτάταιαπότοεπόµενο event Ειδικότερα, ορίζονται µέθοδοι που ποτέ δεν θα ενεργοποιηθούν ρητά στο πρόγραµµα Αλλά, οι µέθοδοι ενεργοποιούνται αυτόµατα όταν ένα event σηµατοδοτεί ότι πρέπει να κληθεί η µέθοδος 61
Ένα απλό παράθυρο Ένα απλό παράθυρο µπορεί να αποτελείται από ένα αντικείµενο της κλάσης JFrame Ένα αντικείµενο JFrame περιλαµβάνει ένα περίγραµµα (border) και τα συνήθη τρία κουµπιά για ελαχιστοποίηση, αλλαγή του µεγέθους και κλείσιµο του παραθύρου ΗκλάσηJFrame βρίσκεται στο package javax.swing JFrame firstwindow = new JFrame(); Ένα JFrame µπορείναέχεισυνιστώσες, όπως κουµπιά, µενού, και ετικέτες κειµένου (text labels) Αυτές οι συνιστώσες µπορεί να προγραµµατίζονται για ενέργειες firstwindow.add(endbutton); Μπορεί να γίνει ορατό χρησιµοποιώντας τη µέθοδο setvisible firstwindow.setvisible(true); 62
Πρώτη επίδειξη του Swing (1/4) 63
Πρώτη επίδειξη του Swing (2/4) 64
Πρώτη επίδειξη του Swing (3/4) 65
Πρώτη επίδειξη του Swing (4/4) 66
Μερικές µέθοδοι της κλάσης JFrame (1/3) 67
Μερικές µέθοδοι της κλάσης JFrame (2/3) 68
Μερικές µέθοδοι της κλάσης JFrame (3/3) 69
Pixels και η σχέση µεταξύ ανάλυσης και µεγέθους Ένα pixel είναι η µικρότερη µονάδα χώρου στην οθόνη Το µέγεθος και η θέση των αντικειµένων του Swing µετρούνται σε pixels Όσο πιο πολλά pixels στην οθόνη, τόσο µεγαλύτερη η ανάλυση της οθόνης Μια οθόνη υψηλής ανάλυσης σταθερού µεγέθους έχει πολλά pixels Εποµένως, κάθε ένα τους είναι πολύ µικρό Μια οθόνη µικρής ανάλυσης σταθερού µεγέθους έχει λιγότερα pixels Εποµένως, κάθε ένα τους είναι πολύ µεγαλύτερο Εποµένως, ένα σχήµα αποτελούµενο από pixels σε µια οθόνη χαµηλής ανάλυσης θα µοιάζει µεγαλύτερο από ότι το ίδιο σχήµα σεµια οθόνη υψηλής ανάλυσης 70
Παγίδα: Ξεχνώντας να προγραµµατίσουµε το κουµπί κλεισίµατος του παραθύρου Οι επόµενες γραµµέςαπότοπρόγραµµα FirstSwingDemo βεβαιώνουν ότι όταν ο χρήστης κάνει click στο κουµπί closewindow, τίποτε δεν συµβαίνει firstwindow.setdefaultcloseoperation( JFrame.DO_NOTHING_ON_CLOSE); Εάν αυτό δεν το θέταµε, ηεξ ορισµού ενέργεια θα ήταν JFrame.HIDE_ON_CLOSE Αυτό θα καθιστούσε το παράθυρο αόρατο και µη προσπελάσιµο, αλλάδεν θα τερµάτιζε το πρόγραµµα Εποµένως, δεδοµένου αυτού του σεναρίου, δεν θα υπήρχε τρόπος να κάνουµε click στο κουµπί "Click to end program" Να σηµειωθεί ότι το κουµπί close-window και τα άλλα δυο συνοδευτικά κουµπιά είναι µέρος του αντικειµένου JFrame, και όχι ξεχωριστά κουµπιά 71
Κουµπιά - Buttons Ένα αντικείµενο κουµπί (button object) δηµιουργείται από την κλάση JButton και µπορεί να προστεθεί σε ένα JFrame Το όρισµαστονconstructor του JButton είναι ένα string που εµφανίζεται στο κουµπί ότι αυτό επιδεικνύεται JButton endbutton= new JButton("Click to end program."); firstwindow.add(endbutton); 72
Action Listeners και Action Events Κάνοντας click σε ένα κουµπί, ενεργοποιείται ένα event Το αντικείµενο event στέλνεται σε ένα άλλο αντικείµενο το οποίο αποκαλείται listener Αυτό σηµαίνει ότι ενεργοποιείται αυτόµατα κάποια µέθοδος του αντικειµένου listener Επιπλέον, ενεργοποιείται µε τοαντικείµενο event ως όρισµά της Για να φτιάξουµεαυτήτησχέση, ένα πρόγραµµα GUI πρέπει να κάνει δυο πράγµατα: 1. Πρέπει να καθορίσει, για κάθε κουµπί, ποια αντικείµενα είναι οι δικοί του listeners, δηλ., πρέπει να καταχωρήσει τους listeners 2. Πρέπει να καθορίσει τις µεθόδους που θα ενεργοποιηθούν αυτόµατα, όταν το event σταλεί στον listener 73
Action Listeners και Action Events EndingListener buttonear = new EndingListener()); endbutton.addactionlistener(buttonear); Παραπάνω, δηµιουργείται ένα αντικείµενο listener µε όνοµα buttonear και καταχωρείται ως listener για το κουµπί µε όνοµα endbutton Σηµειώστε ότι ένα κουµπί ενεργοποιεί events γνωστά ως action events, τα οποία τα χειρίζονται listeners που είναι γνωστοί ως action listeners 74
Action Listeners και Action Events ιαφορετικά είδη συνιστωσών απαιτούν διαφορετικά είδη από κλάσεις listener για να χειριστούν τα events που ενεργοποιούν Ένας action listener είναι ένα αντικείµενο του οποίου ηκλάσηυλοποιείτοinterface ActionListener Το interface ActionListener έχει µια κεφαλίδα µεθόδου που πρέπει να υλοποιηθεί public void actionperformed(actionevent e) 75
Action Listeners και Action Events public void actionperformed(actionevent e) { System.exit(0); } ΗκλάσηEndingListener ορίζει τη µέθοδό της actionperformed όπως παραπάνω Όταν ο χρήστης κάνει clicks το endbutton, ένα action event στέλνεται στον action listener για το κουµπί αυτό Το αντικείµενο buttonear τύπου EndingListener είναι ένας action listener για το endbutton Ο action listener buttonear λαµβάνει το action event ως παράµετρο e στην µέθοδό του actionperformed, η οποία ενεργοποιείται αυτόµατα Σηµειώστε ότι το e πρέπει να ληφθεί, ακόµα και εάν δεν χρησιµοποιηθεί 76
Παγίδα: Αλλάζοντας την κεφαλίδα του actionperformed Όταν υλοποιείται η µέθοδος actionperformed σε έναν action listener, η κεφαλίδα της πρέπει να είναι εκείνη που καθορίζεται στο interface ActionListener Είναι ήδη καθορισµένη, και δεν χρειάζεται να αλλάξει Ούτε να προστεθεί και η δήλωση throws public void actionperformed(actionevent e) Το µόνο πράγµα πουµπορεί να αλλαχτεί είναι το όνοµα της παραµέτρου, αφού είναι απλά ένας placeholder Είτε λέγεται e είτε κάπως αλλιώς δεν παίζει ρόλο, εφόσον χρησιµοποιείται ορθά µέσα στο σώµατηςµεθόδου 77
Υπόδειξη: Τερµατίζοντας ένα Swing πρόγραµµα Τα προγράµµατα GUI βασίζονται συχνά σε ένα είδος ατέρµονα βρόχου Το σύστηµα παραθύρων κανονικά µένει στην οθόνη µέχρι να καθορίσει ο χρήστης ότι πρέπει να φύγει Εάν ο χρήστης δεν το ζητήσει ποτέ, δεν θα εξαφανιστεί Γιανατερµατίσουµε έναπρόγραµµα GUI, πρέπει να χρησιµοποιηθεί η System.exit όταν ζητήσει ο χρήστης τον τερµατισµό του παραθυρικού προγράµµατος Πρέπει να ενεργοποιηθεί ρητά, ήναπεριληφθείσεκώδικα βιβλιοθηκών που εκτελείται Αλλιώς, ένα πρόγραµµα Swing δεν θα τερµατιστεί ακόµα και µετά που έχει εκτελεστεί όλος ο κώδικας του προγράµµατος 78
Μια καλύτερη έκδοση του πρώτου µας προγράµµατος σε Swing GUI Μια καλύτερη έκδοση FirstWindow την κάνει παραγόµενη κλάση της JFrame Αυτός είναι ο ορθός τρόπος να ορίζουµεέναwindowing interface Ο constructor στη νέα κλάση FirstWindow ξεκινά µε κλήσητουconstructor για την πατρική κλάση µε χρήση του super(); Αυτό διαβεβαιώνει ότι οποιαδήποτε αρχικοποίηση γίνει για όλα τα αντικείµενα τύπου JFrame θα λάβει χώρα κανονικά Σχεδόν όλες οι αρχικοποιήσει για το παράθυρο FirstWindow τοποθετείται στον constructor της κλάσης Σηµειώστε ότι αυτή τη φορά, ένα ανώνυµο αντικείµενο χρησιµοποιείται ως ο action listener για το endbutton 79
Ορθόςτρόποςναορίζουµε έναjframe (1/4) 80
Ορθόςτρόποςναορίζουµε έναjframe (2/4) 81
Ορθόςτρόποςναορίζουµε έναjframe (3/4) 82
Ορθόςτρόποςναορίζουµε έναjframe (4/4) 83
Ετικέτες - Labels Μια ετικέτα (label) είναι ένα αντικείµενο της κλάσης JLabel Κείµενο µπορεί να προστεθεί σε ένα JFrame µε χρήσητης ετικέτας Το κείµενο για την ετικέτα δίνεται ως όρισµα όταν δηµιουργείται η JLabel Η ετικέτα κατόπιν µπορεί να προστεθεί στο JFrame JLabel greeting = new JLabel("Hello"); add(greeting); 84
Χρώµα - Color Στη Java, ένα χρώµα (color) είναι ένα αντικείµενο της κλάσης Color ΗκλάσηColor βρίσκεται στο package java.awt Υπάρχουν σταθερές στην κλάση Color που αναπαριστούν ένα αριθµό από βασικά χρώµατα Ένα Jframe δεν µπορεί να χρωµατιστεί κατευθείαν Αλλά, το πρόγραµµα πρέπειναχρωµατίσει αυτό που αποκαλείται το content pane του JFrame Αφού το content pane είναι το µέσα µέρος του JFrame, οχρωµατισµός του content pane έχει ως αποτέλεσµα τον χρωµατισµό τουjframe Εποµένως, το χρώµα υποβάθρου ενός JFrame µπορεί να τεθεί µε τον επόµενο κώδικα: getcontentpane().setbackground(color); 85
Οι σταθερές χρώµατος 86
Ένα JFrame µε χρώµα (1/4) 87
Ένα JFrame µε χρώµα (2/4) 88
Ένα JFrame µε χρώµα (3/4) 89
Ένα JFrame µε χρώµα (4/4) 90
Containers και Layout Managers Πολλαπλές συνιστώσες µπορούν να προστεθούν στο content pane ενός JFrame µε χρήσητης µεθόδου add Όµως, η µέθοδος add δεν καθορίζει πώς θα διαταχτούν αυτές οι συνιστώσες Γιαναπεριγράψουµε πώς θα διαταχτούν πολλαπλές συνιστώσες, χρησιµοποιείται ένας layout manager Υπάρχει ένας αριθµός από κλάσεις που υλοποιούν layout manager, όπως η BorderLayout, FlowLayout, και η GridLayout Εάν δεν καθοριστεί κάποιος layout manager, χρησιµοποιείται ένας εξ ορισµού layout manager 91
Border layout managers Ένας BorderLayout manager τοποθετεί τις συνιστώσες που θα προστεθούν στο αντικείµενο JFrame σε πέντε περιοχές Αυτές οι περιοχές είναι οι: BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST, BorderLayout.WEST, και BorderLayout.Center Ένας BorderLayout manager προστίθεται σε ένα JFrame µε χρήσητηςµεθόδου setlayout Για παράδειγµα: setlayout(new BorderLayout()); 92
Ο BorderLayout manager (1/4) 93
Ο BorderLayout manager (2/4) 94
Ο BorderLayout manager (3/4) 95
Ο BorderLayout manager (4/4) 96
Περιοχές του BorderLayout 97
Border layout managers Το προηγούµενο διάγραµµα δείχνει τη διάταξη των πέντε περιοχών του border layout Σηµείωση: Καµία από τις γραµµές του διαγράµµατος δεν είναι κανονικά ορατή Όταν χρησιµοποιούµε ένανborderlayout manager, ηθέσητηςσυνιστώσαςπου προστίθεται, δίνεται ως δεύτερο όρισµαστη µέθοδο add add(label1, BorderLayout.NORTH); Συνιστώσες µπορούν να προστεθούν µε οποιαδήποτε σειρά αφού καθορίζεται η θέση τους 98
Flow layout managers Ο FlowLayout manager είναι ο απλούστερος layout manager setlayout(new FlowLayout()); Τοποθετεί τις συνιστώσες τη µια µετά την άλλη, από αριστερά προς δεξιά Οι συνιστώσες τοποθετούνται µε τη σειρά που προστίθενται Αφού δεν καθορίζεται η θέση τους, η µέθοδος add έχει µόνο ένα όρισµαότανχρησιµοποιούµε τον FlowLayoutManager add.(label1); 99
Grid layout managers Ο GridLayout manager τοποθετεί τις συνιστώσες σε ένα διδιάστατο πλέγµα (grid) που αποτελείται από γραµµές και στήλες setlayout(new GridLayout(rows, columns)); Κάθε κελί έχει το ίδιο µέγεθος Οι δυο αριθµοί που δίνονται ως όρισµα καθορίζουν τον αριθµό των γραµµών και των στηλών Κάθε συνιστώσα τεντώνεται (stretched) έτσι ώστε να καταλάβει πλήρως την περιοχή του πλέγµατος που τοποθετείται Σηµείωση: Καµία από τις γραµµές του πλέγµατος δεν είναι κανονικά ορατή 100
Grid layout managers Όταν χρησιµοποιούµε τηνκλάσηgridlayout, η µέθοδος add έχει µόνο ένα όρισµα add(label1); Τα items τοποθετούνται στο πλέγµα από αριστερά προς δεξιά Ηπάνωγραµµήγεµίζει πρώτα, κατόπιν η δεύτερη, µετά η τρίτη, κ.ο.κ. εν µπορούµε να παραλείψουµε περιοχές του πλέγµατος Σηµειώστε τη χρήση µιας main µεθόδου στην κλάση του GUI στο επόµενο παράδειγµα Αυτός είναι συνήθως ένας βολικός τρόπος για να επιδεικνύουµε µια κλάση 101
Ο GridLayout manager (1/4) 102
Ο GridLayout manager (2/4) 103
Ο GridLayout manager (3/4) 104
Ο GridLayout manager (4/4) 105
Οι layout managers 106
Panels Ένα GUI οργανώνεται συχνά µειεραρχικήδοµή, µε containers που αποκαλούνται panels µέσα σε άλλους containers Ένα panel είναι ένα αντικείµενο της κλάσης JPanel που λειτουργεί ως απλός container Χρησιµοποιείται για να οµαδοποιήσει µικρότερα αντικείµενα σε µεγαλύτερη συνιστώσα (το panel) Μια από τις κύριες λειτουργίες του αντικειµένου JPanel είναι να υποδιαιρεί ένα JFrame ήκάποιον άλλο container 107
Panels Το JFrame και κάθε panel του JFrame µπορεί να χρησιµοποιούν διαφορετικούς layout managers Επιπρόσθετα panels µπορεί να προστεθούν σε κάθε panel, και κάθε panel µπορείναέχειτοδικότουlayout manager Αυτό επιτρέπει σχεδόν κάθε πιθανή διάταξη σε ένα GUI setlayout(new BorderLayout()); JPanel somepanel = new JPanel(); somepanel.setlayout(new FlowLayout()); Σηµειώστε ότι στο επόµενο παράδειγµα, στα αντικείµενα panel και button δίνεται χρώµα µε χρήση της µεθόδου setbackground χωρίς ενεργοποίηση της getcontentpane Η µέθοδος getcontentpane χρησιµοποιείται µόνο όταν προσθέτουµε χρώµα σεέναjframe 108
Χρήση των panels (1/8) 109
Χρήση των panels (2/8) 110
Χρήση των panels (3/8) 111
Χρήση των panels (4/8) 112
Χρήση των panels (5/8) 113
Χρήση των panels (6/8) 114
Χρήση των panels (7/8) 115
Χρήση των panels (8/8) 116
ΗκλάσηContainer Οποιαδήποτε κλάση είναι απόγονος της κλάσης Container θεωρείται ότι είναι επίσης µια κλάση container ΗκλάσηContainer βρίσκεται στο package java.awt, και όχι στις βιβλιοθήκες του Swing Οποιαδήποτε αντικείµενα ανήκουν σε µια κλάση που παράγεται από την κλάση Container (ήαπότις κλάσεις-απογόνους της) µπορεί να έχουν συνιστώσες που προστίθενται σ αυτά Οι κλάσεις JFrame και JPanel είναι κλάσεις απόγονοι της κλάσης Container Εποµένως, αυτές καθώς και οι απόγονοί τους µπορούν να λειτουργήσουν ως container 117
ΗκλάσηJComponent Οποιαδήποτε κλάση-απόγονος της κλάσης JComponent καλείται component class Οποιοδήποτε αντικείµενο JComponent ή component µπορεί να προστεθεί σε οποιοδήποτε αντικείµενο κλάσης container Επειδή, παράγεται από την κλάση Container, ένα JComponent µπορεί επίσης να προστεθεί σε ένα άλλο JComponent 118
Αντικείµενα σε ένα τυπικό GUI Σχεδόν κάθε GUI που χτίζεται µε χρήσητων container κλάσεων του Swing θα αποτελείται από τρία είδη αντικειµένων: 1. Τον container, πιθανόν ένα panel ή κάποιο παραθυρικού τύπου αντικείµενο 2. Τις συνιστώσες που προστίθενται στον container, όπως ετικέτες, κουµπιά, και panels 3. Έναν layout manager για να διατάξει τις συνιστώσες µέσα στον container 119
Ιεραρχία κλάσεων του Swing και του AWT 120
Υπόδειξη: Κωδικοποιήστε χωριστά την εµφάνιση του GUI και τις ενέργειές του ΗεργασίατηςσχεδίασηςενόςSwing GUI µπορεί να υποδιαιρεθεί σε δυο κύριες υπολειτουργίες: 1. Σχεδίαση και κωδικοποίηση της εµφάνισης του GUI στην οθόνη 2. Σχεδίαση και κωδικοποίηση των ενεργειών που εκτελούνται σε απόκριση των ενεργειών του χρήστη Ειδικότερα, είναι χρήσιµο να υλοποιούµε τηµέθοδο actionperformed ως µια stub, µέχρι το GUI να γίνει έτσι όπως το θέλουµε: public void actionperformed(actionevent e) {} Αυτή η φιλοσοφία είναι η καρδιά της τεχνικής που αποκαλείται πρότυπο Model-View-Controller 121
Το πρότυπο model-view-controller 122
Menu bars, menus, και menu items Ένα menu είναι ένα αντικείµενο της κλάσης JMenu Η επιλογή ενός µενού αποκαλείται menu item, και είναι ένα αντικείµενο της κλάση ςjmenuitem Ένα menu µπορεί να περιέχει οποιοδήποτε αριθµό απόmenu items Ένα menu item προσδιορίζεται από το string που το ονοµατίζει, και επιδεικνύεται µε τη σειρά που προστέθηκε στο menu Η µέθοδος add χρησιµοποιείται για να προσθέσουµε ένα menu item σε ένα menu µε τον ίδιο τρόπο που µια συνιστώσα προστίθεται σε ένα αντικείµενο container 123
Menu bars, menus, και menu items Ο επόµενος κώδικας δηµιουργεί ένα νέο menu, και κατόπιν προσθέτει ένα menu item: JMenu diner = new JMenu("Daily Specials"); JMenuItem lunch = new JMenuItem("Lunch Specials"); lunch.addactionlistener(this); diner.add(lunch); Σηµειώστε ότι η παράµετρος this έχει καταχωρηθεί ως action listener για το menu item 124
Φωλιασµένα menus ΗκλάσηJMenu είναι απόγονος της κλάσηςjmenuitem Κάθε JMenu µπορεί να είναι ένα menu item σε κάποιο άλλο menu Εποµένως, τα menus µπορεί να φωλιάζονται Τα menus µπορεί να προστίθενται σε άλλα menus µε τον ίδιο τρόποι όπως και τα menu items 125
Menu bars και JFrame Ένα menu bar είναι ένας container για menus, τυπικά τοποθετούνται κοντά στην κορυφή του windowing interface Η µέθοδος add χρησιµοποιείται για να προσθέτουµε ένα menu σε µια menu bar µε τον ίδιο τρόπο που τα menu items προστίθενται σε ένα menu JMenuBar bar = new JMenuBar(); bar.add(diner); Η menu bar µπορεί να προστεθεί σε ένα JFrame µε δυο τρόπους: 1. Με χρήση της µεθόδου setjmenubar setjmenubar(bar); 2. Με χρήση της µεθόδου add που µπορεί να χρησιµοποιηθεί για να προσθέσουµε µια menu bar σε ένα JFrame ή οποιοδήποτε άλλο container 126
Ένα GUI µεέναmenu (1/8) 127
Ένα GUI µεέναmenu (2/8) 128
Ένα GUI µεέναmenu (3/8) 129
Ένα GUI µεέναmenu (4/8) 130
Ένα GUI µεέναmenu (5/8) 131
Ένα GUI µεέναmenu (6/8) 132
Ένα GUI µεέναmenu (7/8) 133
Ένα GUI µεέναmenu (8/8) 134
Οι κλάσεις AbstractButton και Dimension Οι κλάσεις JButton και JMenuItem είναι παραγόµενες κλάσεις της abstract κλάσης µε όνοµα AbstractButton Όλες οι βασικές τους µέθοδοι και ιδιότητες κληρονοµούνται από την κλάση AbstractButton Τα αντικείµενα της κλάσης Dimension χρησιµοποιούνται µε κουµπιά, menu items, και άλλα αντικείµενα για να καθορίζουν ένα µέγεθος ΗκλάσηDimension βρίσκεται στο package java.awt Dimension(int width, int height) Σηµείωση: οι παράµετροι width και height µετρούνται σε pixels 135
Η µέθοδος setactioncommand Όταν ένας χρήστης κάνει click σε ένα κουµπί ή σε ένα menu item, ενεργοποιείται ένα event, το οποίο φυσιολογικά πηγαίνει σε έναν ή περισσότερους action listeners Το action event γίνεται όρισµα σε µια µέθοδοactionperformed Αυτό το action event περιλαµβάνει µια instance variable τύπου String που καλείται action command για το κουµπί ή το menu item Ηεξ ορισµού τιµήγιατονstring αυτό είναι το string που αναγράφεται στο κουµπί ή στο menu item Αυτό το string µπορεί να ανακτηθεί µε τη µέθοδοgetactioncommand e.getactioncommand() 136
Η µέθοδος setactioncommand Η µέθοδος setactioncommand µπορεί να χρησιµοποιηθεί για να αλλάξει την εντολή ενέργειας για µια συνιστώσα Αυτό είναι ιδιαίτερα χρήσιµο όταν δυο ή περισσότερα κουµπιά ή menu items έχουν τα ίδια εξ ορισµού action command strings JButton nextbutton = new JButton("Next"); nextbutton.setactioncommand("next Button"); JMenuItem choose = new JMenuItem("Next"); choose.setactioncommand("next Menu Item"); 137
Μερικές µέθοδοι της κλάσης AbstractButton (1/3) 138
Μερικές µέθοδοι της κλάσης AbstractButton (2/3) 139
Μερικές µέθοδοι της κλάσης AbstractButton (3/3) 140
Listeners ως inner κλάσεις Συχνά, αντί να έχουµε ένααντικείµενο ως action listener για να χειρίζεται όλα τα action events σε ένα GUI, µια χωριστή κλάση ActionListener δηµιουργείται για κάθε κουµπί ή menu item Κάθε κουµπί ή menu item έχει τον δικό του µοναδικό action listener εν υπάρχει ανάγκη για multiway if-else δήλωση Όταν χρησιµοποιείται αυτή η προσέγγιση, κάθε κλάση γίνεται συνήθως µια private inner κλάση 141
Listeners ως inner κλάσεις (1/6) 142
Listeners ως inner κλάσεις (2/6) 143
Listeners ως inner κλάσεις (3/6) 144
Listeners ως inner κλάσεις (4/6) 145
Listeners ως inner κλάσεις (5/6) 146
Listeners ως inner κλάσεις (6/6) 147
Πεδία κειµένου - Text fields Ένα text field είναι ένα αντικείµενο της κλάσης JTextField Εικονίζεται ως ένα πεδίο που επιτρέπει στον χρήστη να εισαγάγει µια απλή γραµµήκειµένου private JTextField name;... name = new JTextField(NUMBER_OF_CHAR); Στον πιο πάνω text field, το πολύ NUMBER_OF_CHAR χαρακτήρες µπορεί να είναι ορατοί 148
Πεδία κειµένου - Text fields Υπάρχει επίσης ένας constructor µε µια επιπλέον String παράµετρο για να απεικονίζει ένα αρχικό String στο text field JTextField name=new JTextField("Enter name here.",30); Ένα Swing GUI µπορείναδιαβάσειτοκείµενο για ένα text field µε χρήσητηςµεθόδου gettext String inputstring = name.gettext(); Η µέθοδος settext µπορεί να χρησιµοποιηθεί για να επιδείξει ένα νέο text string σε ένα text field name.settext("this is some output"); 149
Ένα text field (1/7) 150
Ένα text field (2/7) 151
Ένα text field (3/7) 152
Ένα text field (4/7) 153
Ένα text field (5/7) 154
Ένα text field (6/7) 155
Ένα text field (7/7) 156
Περιοχές κειµένου - Text areas Μια text area είναι ένα αντικείµενο της κλάσης JTextArea Είναιτοίδιοόπωςέναtext field, εκτός από το ότι επιτρέπει πολλαπλές γραµµές Οι δυο παράµετροι στον constructor της JTextArea καθορίζουν τον ελάχιστο αριθµό γραµµών, και τον ελάχιστο αριθµό χαρακτήρων ανά γραµµή, για τους/τις οποίους/οποίες υπάρχει εγγύηση ότι θα είναι ορατοί/ορατές JTextArea thetext = new JTextArea(5,20); Ένας άλλος constructor έχει µια επιπλέον παράµετρο τύπου String για το string που αρχικά δείχνεται στην text area JTextArea thetext = new JTextArea( "Enter\ntext here." 5, 20); 157
Περιοχές κειµένου - Text areas Η πολιτική αναδίπλωση γραµµής (linewrapping) της JTextArea µπορεί να τεθεί µε τη µέθοδο setlinewrap Η µέθοδος δέχεται ένα όρισµα τύπουboolean Εάν το όρισµα είναιtrue, τότε οποιοιδήποτε επιπλέον χαρακτήρες στο τέλος της γραµµής θα εµφανιστούνστηνεπόµενη γραµµήτηςtext area Εάν το όρισµα είναιfalse, οι επιπλέον χαρακτήρες θα παραµείνουν στην ίδια γραµµή και δεν θα είναι ορατοί thetext.setlinewrap(true); 158
Text fields και text areas Μια JTextField ή JTextArea µπορεί να τεθεί έτσι ώστε να µην µπορεί να τροποποιηθεί από τον χρήστη thetext.seteditable(false); Αυτό θα θέσει το thetext έτσι ώστε να µπορεί µόνο να τροποποιηθεί από το GUI πρόγραµµα, και όχι από τον χρήστη Γιανατοαναστρέψουµε, θα χρησιµοποιήσουµε το true (αυτό είναι το εξ ορισµού) thetext.seteditable(true); 159
Υπόδειξη: Ετικέτα σε ένα text field Γιαναβάλουµεετικέτασεέναήπερισσότερα text fields: Χρησιµοποιούµε ένααντικείµενο της κλάσης JLabel Τοποθετούµε το/τα text field(s) και ετικέτα/ες σε ένα JPanel Θεωρούµε τοjpanel ως µια συνιστώσα 160
Αριθµός χαρακτήρων ανά γραµµή Οαριθµός των χαρακτήρων ανά γραµµήγιαένα αντικείµενο JTextField ή JTextArea είναι οαριθµός των em spaces Ένα em space είναι ο χώρος που χρειάζεται για να κρατηθεί ένα κεφαλαίο M Το γράµµα M είναι το πλατύτερο γράµµα της αλφαβήτου Μια γραµµή που καθορίζεται να κρατήσει 20 M θα µπορεί σχεδόν πάντα να κρατήσει περισσότερους από 20 χαρακτήρες 161
Υπόδειξη: Είσοδος & έξοδος αριθµών Όταν επιχειρούµεναεισαγάγουµε αριθµούς από ένα Swing GUI, το κείµενο εισόδου πρέπει να µετατραπεί σε αριθµό Εάν ο χρήστης εισαγάγει τον αριθµό 42 σε ένα JTextField, το πρόγραµµα λαµβάνει το string "42" και πρέπει να το µετατρέψει στον ακέραιο 42 Το ίδιο ισχύει όταν επιχειρούµενατυπώσουµε έναν αριθµό Γιανατυπώσουµε τον αριθµό 42, πρέπει πρώτα να τον µετατρέψουµε στοstring "42" 162
ΗκλάσηJTextComponent Οι JTextField και JTextArea είναι παραγόµενες κλάσεις της abstract class JTextComponent Οι περισσότερες από τις µεθόδους τους κληρονοµούνται από τη JTextComponent και έχουν την ίδια σηµασία Εκτός από κάποιους µικρούς επανορισµούς για να λάβουν υπόψη το ότι έχουν µόνο µια ή πολλαπλές γραµµές 163
Μερικές µέθοδοι της JTextComponent (1/2) 164
Μερικές µέθοδοι της JTextComponent (2/2) 165
Ένας υπολογιστήρας µε Swing Ένα GUI για έναν απλό υπολογιστήρα κρατά το τρέχον άθροισµα κάποιων αριθµών Ο χρήστης εισάγει ένα αριθµό σεέναtext field, και κατόπιν κάνει click είτε στο + είτε στο Οαριθµός στο text field προστίθεται ή αφαιρείται από το τρέχον άθροισµα, και επιδεικνύεται στο text field Αυτή η τιµή διατηρείται στην instance variable result Όταν εκτελείται για πρώτη φορά το GUI, ή ότανο χρήστης κάνει click στο κουµπί Reset, ητιµήτου result µηδενίζεται 166
Ένας υπολογιστήρας µε Swing Εάν ο χρήστης εισαγάγει έναν αριθµό σεµη έγκυρη µορφή, τότε κάποια από τις µεθόδους πετάει µια NumberFormatException Η εξαίρεση πιάνεται στο catch µπλοκ µέσα στη µέθοδο actionperformed Σηµειώστε ότι όταν πετάγεται αυτή η εξαίρεση, ητιµή της instance variable result δεν αλλάζει 167
Ένας απλός υπολογιστήρας (1/11) 168
Ένας απλός υπολογιστήρας (2/11) 169
Ένας απλός υπολογιστήρας (3/11) 170
Ένας απλός υπολογιστήρας (4/11) 171
Ένας απλός υπολογιστήρας (5/11) 172
Ένας απλός υπολογιστήρας (6/11) 173
Ένας απλός υπολογιστήρας (7/11) 174
Ένας απλός υπολογιστήρας (8/11) 175
Ένας απλός υπολογιστήρας (9/11) 176
Ένας απλός υπολογιστήρας (10/11) 177
Ένας απλός υπολογιστήρας (11/11) 178