Προγραμματισμός

Ξεκινώντας με το Java 2D

Το Java 2D API είναι ένα βασικό API πλατφόρμας Java 1.2 (ανατρέξτε στην ενότητα Πόροι για μια ποικιλία πληροφοριών σχετικά με το API και τις υλοποιήσεις του). Οι υλοποιήσεις του API είναι διαθέσιμες ως μέρος των Java Foundation Classes (JFC) στις τρέχουσες εκδόσεις beta του Sun JDK για Windows NT / 95 και Solaris. Καθώς η Java 1.2 έχει οριστικοποιηθεί, το Java 2D θα πρέπει να είναι διαθέσιμο σε περισσότερες πλατφόρμες.

Σημειώστε ότι παρόλο που το Java 2D έχει αναπτυχθεί κάπως ανεξάρτητα από τα άλλα μέρη του JFC, είναι ωστόσο ένα βασικό μέρος του 1.2 AWT. Θα κάνουμε τη διάκριση και θα επισημάνουμε τις ειδικές λειτουργίες 2D για συζήτηση, αλλά θα πρέπει να θυμάστε ότι αυτή η λειτουργικότητα είναι εξίσου κεντρική με 1,2 γραφικά με την παλιά υποστήριξη 1.0 και 1.1 AWT.

Το Java 2D επεκτείνει τους προηγούμενους μηχανισμούς AWT για σχεδίαση γραφικών 2D, χειρισμό κειμένου και γραμματοσειρών, φόρτωση και χρήση εικόνων, καθώς και καθορισμό και αντιμετώπιση χρωμάτων και χρωμάτων. Θα διερευνήσουμε αυτούς τους νέους μηχανισμούς σε αυτήν και σε μελλοντικές στήλες.

Μια σημείωση για την ονοματολογία και τις συμβάσεις

Για αυτήν τη στήλη, η κύρια πλατφόρμα ανάπτυξης θα είναι ένας υπολογιστής με Windows 95 ή Windows NT. Ελπίζω να δώσω άλλες συμβουλές και κόλπα για συγκεκριμένη πλατφόρμα όπου είναι δυνατόν, αλλά θα επικεντρωθώ στα Windows, καθώς εκεί θα περνάω τον περισσότερο χρόνο μου.

Όταν γράφω ένα όνομα μεθόδου, θα πρέπει πάντα να έχει τη μορφή όνομα μεθόδου (). Οι τελικές παρενθέσεις προορίζονται να το ξεχωρίσουν ως μέθοδο. Η μέθοδος μπορεί να λαμβάνει ή όχι παραμέτρους. Στην πράξη, το πλαίσιο πρέπει πάντα να το καθιστά σαφές.

Οι λίστες πηγαίου κώδικα θα δοθούν με τους αριθμούς γραμμής που περιλαμβάνονται Σκοπεύω να χρησιμοποιήσω τους αριθμούς γραμμής για να παραπέμψω το κείμενο του άρθρου και τις καταχωρίσεις κωδικών, όπως απαιτείται Αυτό θα σας διευκολύνει επίσης να προσθέσετε σχόλια στη στήλη, εάν επιλέξετε να εκτυπώσετε ένα αντίγραφο. Λάβετε υπόψη, ωστόσο, ότι τα αρχεία προέλευσης που συνδέονται από τη στήλη θα είναι κανονικά αρχεία * .java (αριθμοί γραμμής sans), ώστε να μπορείτε να κάνετε λήψη και ανάπτυξη μαζί τους.

Επειδή θα γράψω πολλά από τα API πολυμέσων και επικοινωνιών τους επόμενους μήνες, θέλω να βεβαιωθώ ότι όλο το δείγμα κώδικα έχει νόημα στο σύνολό του, καθώς και στα μεμονωμένα μέρη του. Θα προσπαθήσω να ονομάσω με συνέπεια τα παραδείγματα μου και να τα τοποθετήσω σε λογικά πακέτα.

Η κορυφή της ιεραρχίας των πακέτων μου θα είναι:

com.javaworld.media 

Κάθε API ή θέμα για το οποίο γράφω θα έχει τουλάχιστον ένα δευτερεύον πακέτο σε αυτό το ανώτερο επίπεδο. Για παράδειγμα, όλος ο κώδικας για αυτό το άρθρο Java 2D θα είναι:

com.javaworld.media.j2d 

Έτσι, για να καλέσετε το πρώτο παράδειγμα εφαρμογής στο Java 2D, θα κάνατε λήψη του κώδικα, θα το βάλατε στο classpath και, στη συνέχεια, χρησιμοποιήστε:

java com.javaworld.media.j2d. Παράδειγμα01 

(Εάν ο χώρος ονομάτων είναι πολύ μεγάλος για τις προτιμήσεις σας ή για κάποιο άλλο λόγο θέλετε να χρησιμοποιήσετε το παράδειγμα παραδείγματος χωρίς να χρειάζεται να χρησιμοποιήσετε το πλήρως αναγνωρισμένο όνομα, απλώς σχολιάστε τη γραμμή πακέτου στην αρχή κάθε αρχείου πηγαίου κώδικα.)

Θα δημιουργήσω ένα αρχείο Java Archive (jar) για κάθε παράδειγμα κώδικα κώδικα και αρχεία κλάσης. Αυτό το αρχείο θα είναι διαθέσιμο στους πόρους κάθε στήλης, εάν θέλετε να το κατεβάσετε και να εκτελέσετε τα παραδείγματα μέσα από το αρχείο.

Θα διατηρήσω επίσης ένα ενημερωμένο αρχείο βάζου που περιέχει όλο τον κώδικα και τις τάξεις από το τρέχον και το προηγούμενο Προγραμματισμός πολυμέσων στήλες. Αυτό το πλήρες αρχείο βάζων θα είναι διαθέσιμο στον προσωπικό μου ιστότοπο.

Ένα τελευταίο σημείο σχετικά με τα παραδείγματα: Έχω επιλέξει να κάνω κάθε παράδειγμα, εκτός αν σημειώσω διαφορετικά, μια αυτόνομη εφαρμογή ή μικροεφαρμογή. Αυτό θα οδηγήσει σε κάποια επανάληψη κώδικα από καιρό σε καιρό, αλλά πιστεύω ότι διατηρεί καλύτερα την ακεραιότητα κάθε μεμονωμένου παραδείγματος.

Αρκετά για τις συμβάσεις. Ας ξεκινήσουμε τον προγραμματισμό με το Java 2D!

Graphics2D: Μια καλύτερη κατηγορία γραφικών

Η κεντρική κλάση στο Java 2D API είναι το java.awt.Γραφικά2D αφηρημένη τάξη, η οποία υποκατηγορίες java.awt. Γραφικά να επεκτείνει τη λειτουργικότητα απόδοσης 2D. Γραφικά 2D προσθέτει πιο ομοιόμορφη υποστήριξη για χειρισμούς ποικίλων σχημάτων, στην πραγματικότητα δημιουργία κειμένου, γραμμών και όλων των ειδών άλλων δισδιάστατων σχημάτων συγκρίσιμων στις δυνατότητες και τη χρησιμότητά τους.

Ας ξεκινήσουμε με ένα απλό παράδειγμα που δείχνει πώς παίρνετε και χρησιμοποιείτε το Γραφικά2d αναφορά.

001 πακέτο com.javaworld.media.j2d; 002 003 εισαγωγή java.awt. *; 004 εισαγωγή java.awt.event. *; 005 006 δημόσια τάξη Το Παράδειγμα01 επεκτείνει το Πλαίσιο {007 / ** 008 * Εγκαθιστά ένα αντικείμενο Παράδειγμα01. 009 ** / 010 public static void main (String args []) {011 new Example01 (); 012} 013 014 / ** 015 * Ο κατασκευαστής μας Παράδειγμα01 ορίζει το μέγεθος του πλαισίου, προσθέτει τα οπτικά στοιχεία 016 * και, στη συνέχεια, τα καθιστά ορατά στον χρήστη. 017 * Χρησιμοποιεί τάξη προσαρμογέα για να αντιμετωπίσει το χρήστη που κλείνει 018 * το πλαίσιο. 019 ** / 020 δημόσια Παράδειγμα01 () {021 // Τίτλος του πλαισίου μας. 022 super ("Java 2D Παράδειγμα01"); 023 024 // Ορίστε το μέγεθος για το πλαίσιο. 025 setSize (400.300); 026 027 // Πρέπει να ενεργοποιήσουμε την ορατότητα του καρέ μας 028 // ρυθμίζοντας την παράμετρο Ορατή σε πραγματική. 029 setVisible (true); 030 031 // Τώρα, θέλουμε να είμαστε σίγουροι ότι διαθέτουμε σωστά πόρους 032 // αυτό το πλαίσιο χρησιμοποιεί όταν το παράθυρο είναι κλειστό. Χρησιμοποιούμε 033 // έναν ανώνυμο προσαρμογέα εσωτερικής τάξης για αυτό. 034 addWindowListener (new WindowAdapter () 035 {public void windowClosing (WindowEvent e) 036 {dispose (); System.exit (0);} 037} 038); 039} 040 041 / ** 042 * Η μέθοδος βαφής παρέχει την πραγματική μαγεία. Εδώ 043 * ρίχνουμε το αντικείμενο Graphics στο Graphics2D για να δείξουμε το 044 * ότι μπορούμε να χρησιμοποιήσουμε τις ίδιες παλιές δυνατότητες γραφικών με το 045 * Graphics2D που έχουμε συνηθίσει να χρησιμοποιούμε με το Graphics. 046 ** / 047 δημόσιο άδειο χρώμα (Γραφικά g) {048 // Εδώ είναι πώς σχεδιάσαμε ένα τετράγωνο με πλάτος 049 // 200, ύψος 200 και ξεκινώντας από x = 50, y = 50. 050 g.setColor (Color.red); 051 g.drawRect (50,50,200,200); 052 053 // Ας ρυθμίσουμε το χρώμα σε μπλε και, στη συνέχεια, χρησιμοποιήστε το αντικείμενο Graphics2D 054 // για να σχεδιάσετε ένα ορθογώνιο, μετατοπισμένο από το τετράγωνο. 055 // Μέχρι στιγμής, δεν έχουμε κάνει τίποτα χρησιμοποιώντας το Graphics2D που το 056 // δεν θα μπορούσαμε επίσης να κάνουμε χρησιμοποιώντας το Graphics. (Στην πραγματικότητα χρησιμοποιούμε 057 // μεθόδους Graphics2D που κληρονομούνται από το Graphics.) 058 Graphics2D g2d = (Graphics2D) g; 059 g2d.setColor (Color.blue); 060 g2d.drawRect (75,75.300.200); 061} 062} 

Όταν εκτελείτε το Παράδειγμα01, θα πρέπει να δείτε ένα κόκκινο τετράγωνο και ένα μπλε ορθογώνιο, όπως φαίνεται στο παρακάτω σχήμα. Σημειώστε ότι υπάρχει ένα γνωστό πρόβλημα απόδοσης με την έκδοση Windows NT / 95 του JDK 1.2 Beta 3 (η πιο πρόσφατη έκδοση 1.2 από αυτήν τη στήλη). Εάν αυτό το παράδειγμα είναι οδυνηρά αργό στο σύστημά σας, ίσως χρειαστεί να επιλύσετε το σφάλμα όπως τεκμηριώνεται στο JavaWorldΣυμβουλή Java 55 (βλ. παρακάτω πόρους για αυτήν την συμβουλή).

Σημειώστε ότι ακριβώς όπως δεν δημιουργείτε άμεσα α Γραφικά αντικείμενο, δεν δημιουργείτε ένα Γραφικά 2D είτε αντικείμενο. Αντίθετα, ο χρόνος εκτέλεσης Java κατασκευάζει ένα αντικείμενο απόδοσης και το μεταδίδει χρώμα() (γραμμή 047 στη λίστα κώδικα του παραδείγματος01), και σε πλατφόρμες Java 1.2 και μετά, αυτό το αντικείμενο εφαρμόζει το Γραφικά 2D αφηρημένη τάξη επίσης.

Μέχρι στιγμής δεν έχουμε κάνει κάτι ιδιαίτερο με τις δυνατότητες γραφικών 2D. Ας προσθέσουμε κάποιο κωδικό στο τέλος των προηγούμενων παραδειγμάτων μας χρώμα() μέθοδο και να φέρει πολλά χαρακτηριστικά νέα στο Java 2D (Παράδειγμα02):

001 / ** 002 * Εδώ χρησιμοποιούμε νέες δυνατότητες Java 2D API, όπως μετασχηματισμοί affine 003 * και αντικείμενα σχήματος (σε αυτήν την περίπτωση ένα γενικό 004 * ένα, GeneralPath). 005 ** / 006 δημόσια κενή βαφή (Γραφικά g) {007 g.setColor (Color.red); 008 g.drawRect (50,50,200,200); 009 010 Graphics2D g2d = (Graphics2D) g; 011 g2d.setColor (Color.blue); 012 g2d.drawRect (75,75.300.200); 013 014 // Τώρα, ας σχεδιάσουμε ένα άλλο ορθογώνιο, αλλά αυτή τη φορά, ας 015 // χρησιμοποιήσουμε ένα GeneralPath για να το καθορίσουμε ανά τμήμα. 016 // Επιπλέον, πρόκειται να μεταφράσουμε και να περιστρέψουμε αυτό το ορθογώνιο 017 // σε σχέση με το Διάστημα Συσκευής (και έτσι, στο 018 // τα δύο πρώτα τετράπλευρα) χρησιμοποιώντας ένα AffineTransform. 019 // Θα αλλάξουμε επίσης το χρώμα του. 020 Path GeneralPath = νέο GeneralPath (GeneralPath.EVEN_ODD); 021 path.moveTo (0,0f, 0,0f); 022 path.lineTo (0.0f, 125.0f); 023 path.lineTo (225.0f, 125.0f); 024 path.lineTo (225.0f, 0.0f); 025 path.closePath (); 026 027 AffineTransform at = new AffineTransform (); 028 at.setToRotation (-Math.PI / 8.0); 029 g2d.transform (at); 030 at.setToTranslation (50.0f, 200.0f); 031 g2d.transform (at); 032 033 g2d.setColor (Color.green); 034 g2d.fill (διαδρομή); 035} 

Σημειώστε ότι από τότε Γενική διαδρομή βρίσκεται στο java.awt.geom πακέτο, πρέπει να είμαστε σίγουροι ότι προσθέτουμε επίσης μια γραμμή εισαγωγής:

εισαγωγή java.awt.geom. *; 

Η έξοδος του παραδείγματος 02 φαίνεται στο ακόλουθο σχήμα.

Το Java 2D επιτρέπει τον προσδιορισμό αυθαίρετων σχημάτων χρησιμοποιώντας το java.awt. Σχήμα διεπαφή. Μια ποικιλία προεπιλεγμένων σχημάτων όπως ορθογώνια, πολύγωνα, γραμμές 2D κ.λπ., εφαρμόζουν αυτήν τη διεπαφή. Ένα από τα πιο ενδιαφέροντα από την άποψη της ευελιξίας είναι java.awt.geom.GeneralPath.

Γενική διαδρομήΣας επιτρέπει να περιγράψετε μια διαδρομή με αυθαίρετο αριθμό άκρων και δυνητικά εξαιρετικά περίπλοκο σχήμα. Στο Παράδειγμα02, έχουμε δημιουργήσει ένα ορθογώνιο (γραμμές 020-025), αλλά εξίσου εύκολα θα μπορούσαμε να προσθέσουμε μια άλλη πλευρά ή πλευρές για να φτιάξουμε ένα πεντάγωνο, ή επτάγωνο ή κάποιο άλλο πολύπλευρο πολύγωνο. Σημειώστε επίσης ότι σε αντίθεση με το πρότυπο Γραφικά κώδικα, το Java 2D μας επιτρέπει να καθορίσουμε συντεταγμένες χρησιμοποιώντας αριθμούς κινητής υποδιαστολής αντί για ακέραιους αριθμούς. Προμηθευτές CAD του κόσμου, χαρείτε! Στην πραγματικότητα, το Java 2D υποστηρίζει ακέραιος αριθμός, διπλό, και επιπλέων αριθμητική σε πολλά μέρη.

Ίσως παρατηρήσατε επίσης ότι όταν δημιουργήσαμε τη διαδρομή περάσαμε μια παράμετρο, GeneralPath.EVEN_ODD, στον κατασκευαστή (γραμμή 020). Αυτή η παράμετρος αντιπροσωπεύει ένα κανόνας περιέλιξης που λέει στον renderer πώς να προσδιορίσει το εσωτερικό του σχήματος που καθορίζεται από τη διαδρομή μας. Ανατρέξτε στην τεκμηρίωση Java 2D javadoc που αναφέρεται στους πόρους για περισσότερα σχετικά με τους κανόνες περιέλιξης Java 2D.

Η άλλη σημαντική καινοτομία στο Παράδειγμα 02 περιστρέφεται γύρω από τη χρήση του a java.awt.geom.AffineTransforms (γραμμές 027-031). Θα αφήσω τις ιδιαιτερότητες αυτών των μετασχηματισμών στον αναγνώστη (βλ. Πόρους για άρθρα που το συζητούν λεπτομερέστερα), αλλά αρκεί να πούμε ότι Μετασχηματισμός AffineΣας επιτρέπει να λειτουργείτε σε οποιοδήποτε γραφικό Java 2D για να το μεταφράσετε (να το μετακινήσετε), να το περιστρέψετε, να το κλιμακώσετε, να το κόψετε ή να κάνετε συνδυασμούς αυτών των χειρισμών.

Το κλειδί για Μετασχηματισμός Affine βρίσκεται στην έννοια του Χώρος συσκευής και Χώρος χρήστη. Device Space είναι εκείνη η περιοχή στην οποία θα εμφανίζονται τα γραφικά στην οθόνη. Αυτό είναι ανάλογο με τις συντεταγμένες που χρησιμοποιούνται όταν δημιουργείται ένα κανονικό στυλ AWT Γραφικά- 2D γραφικά. Ο Χώρος Χρήστη, ωστόσο, είναι ένα μεταφράσιμο, περιστρεφόμενο σύστημα συντεταγμένων που μπορεί να λειτουργεί από ένα ή περισσότερα Μετασχηματισμός Affineμικρό.

Συστήματα συντεταγμένων Space Device και User Space επικαλύπτονται αρχικά, με την προέλευση στην επάνω αριστερή πλευρά της επιφάνειας απόδοσης (εδώ, ένα πλαίσιο). Ο θετικός άξονας x κινείται ακριβώς από την αρχή, ενώ ο θετικός άξονας y κινείται προς τα κάτω.

Μετά τον πρώτο μετασχηματισμό στο Παράδειγμα02 (γραμμές 028 και 029), το σύστημα συντεταγμένων Χώρου Χρήστη περιστράφηκε 22,5 μοίρες αριστερόστροφα σε σχέση με το Διάστημα συσκευής. Και οι δύο εξακολουθούν να έχουν την ίδια προέλευση. (Σημειώστε ότι οι περιστροφές καθορίζονται σε ακτίνια, με ακτίνια -PI / 8 ίσο με -22,5 μοίρες ή 22,5 μοίρες CCW.) Αν θέλαμε να σταματήσουμε εδώ και να σχεδιάσουμε το ορθογώνιο, θα περιστρέφονταν κυρίως έξω από το οπτικό πεδίο εφαρμογή Πλαίσιο.

Στη συνέχεια εφαρμόζουμε έναν δεύτερο μετασχηματισμό (γραμμές 030 και 031), αυτός είναι μια μετάφραση, αφού ολοκληρωθεί η περιστροφή. Αυτό μετακινεί το σύστημα συντεταγμένων του Χώρου Χρήστη σε σχέση με το Διάστημα Συσκευής, μετατοπίζοντας το κάτω από τις μονάδες 200,0 (float) και δεξιά τις μονάδες 50,0 (float).

Όταν συμπληρώνουμε το πράσινο ορθογώνιο, μεταφράζεται και περιστρέφεται σε σχέση με το Device Space.

Από καμπύλες Bezier και υψηλότερης τάξης

Τώρα που εξετάσαμε πώς μπορούν να χρησιμοποιηθούν οι μετασχηματισμοί για τον χειρισμό γραφικών αντικειμένων, ας επανεξετάσουμε τον τρόπο με τον οποίο χτίζουμε περίπλοκα και ενδιαφέροντα αυθαίρετα σχήματα.

Οι καμπύλες χρησιμοποιούνται σε όλα τα μαθηματικά και τα γραφικά υπολογιστών για την προσέγγιση πολύπλοκων σχημάτων χρησιμοποιώντας έναν πεπερασμένο, καλά καθορισμένο (και ιδανικά μικρό) αριθμό μαθηματικών σημείων. Ενώ το τυπικό AWT δεν υποστήριζε άμεσα σχέδιο με αυθαίρετες καμπύλες στο παρελθόν (πλατφόρμες Java 1.0 ή 1.1), το Java 2D προσθέτει ενσωματωμένη υποστήριξη για καμπύλες πρώτης, δεύτερης και τρίτης τάξης. Μπορείτε να σχεδιάσετε καμπύλες με δύο τελικά σημεία και μηδέν, ένα ή δύο σημεία ελέγχου. Το Java 2D υπολογίζει καμπύλες πρώτης και δεύτερης τάξης χρησιμοποιώντας γραμμικούς και τετραγωνικούς τύπους και κυβικές ή τρίτης τάξης καμπύλες χρησιμοποιώντας καμπύλες Bezier.

(Οι καμπύλες Bezier είναι ένας τύπος παραμετρικής πολυωνυμικής καμπύλης που έχει μερικές πολύ επιθυμητές ιδιότητες που σχετίζονται με τον υπολογισμό κλειστών καμπυλών και επιφανειών. Χρησιμοποιούνται σε πολλές εφαρμογές γραφικών. Ανατρέξτε στους πόρους για περισσότερες πληροφορίες σχετικά με τη χρήση παραμετρικών πολυωνύμων και καμπυλών Bezier στα γραφικά υπολογιστών.) Το Γενική διαδρομή Οι μέθοδοι που σχεδιάζουν καθεμία από αυτές τις καμπύλες είναι:

  • lineTo () για ευθεία τμήματα (προσδιορίστε μόνο τα τελικά σημεία)
  • τετραπλή () για τετραγωνικές καμπύλες (προσδιορίστε ένα σημείο ελέγχου)
  • καμπύλη Προς () για καμπύλες τρίτης τάξης (προσδιορίστε δύο σημεία ελέγχου, που σχεδιάστηκαν χρησιμοποιώντας κυβική καμπύλη Bezier)