Bermula dengan Java 2D

Java 2D API adalah API platform Java 1.2 inti (lihat Sumber untuk berbagai informasi tentang API dan implementasinya). Pelaksanaan API tersedia sebagai bagian dari Java Foundation Classes (JFC) dalam rilis beta Sun JDK terkini untuk Windows NT / 95 dan Solaris. Ketika Java 1.2 diselesaikan, Java 2D seharusnya tersedia di lebih banyak platform.

Perhatikan bahawa walaupun Java 2D telah dikembangkan agak bebas dari bahagian lain dari JFC, ia tetap merupakan bahagian inti dari 1.2 AWT. Kami akan membezakan dan menunjukkan ciri khusus 2D untuk perbincangan, tetapi anda harus ingat bahawa fungsi ini sama pentingnya dengan 1.2 grafik seperti sokongan AWT 1.0 dan 1.1 yang lama.

Java 2D memperluas mekanisme AWT sebelumnya untuk menggambar grafik 2D, memanipulasi teks dan fon, memuat dan menggunakan gambar, dan menentukan dan menangani warna dan ruang warna. Kami akan meneroka mekanisme baru ini di ruangan ini dan masa depan.

Catatan mengenai tatanama dan konvensyen

Untuk ruangan ini, platform pengembangan utama saya adalah PC yang menjalankan Windows 95 atau Windows NT. Saya berharap dapat memberikan petua dan trik khusus platform lain di mana mungkin, tetapi saya akan memberi tumpuan kepada Windows kerana di situlah saya akan menghabiskan sebahagian besar masa saya.

Semasa saya menulis nama kaedah, mestilah selalu dalam bentuk methodname(). Tanda kurung tertutup dimaksudkan untuk membezakannya sebagai kaedah. Kaedah ini mungkin atau tidak mengambil parameter. Dalam praktiknya, konteksnya harus selalu menjadikan ini jelas.

Senarai kod sumber akan diberikan dengan nombor baris disertakan. Saya merancang untuk menggunakan nombor baris untuk merujuk teks artikel dan senarai kod yang sesuai. Ini juga akan menjadikan anda lebih mudah untuk memberi penjelasan pada lajur, sekiranya anda memilih untuk mencetak salinan. Walau bagaimanapun, harap perhatikan bahawa fail sumber yang dihubungkan dari lajur akan menjadi fail * .java biasa (tanpa garis nombor) sehingga anda dapat memuat turun dan mengembangkannya.

Oleh kerana saya akan menulis tentang banyak API Media dan Komunikasi pada bulan-bulan mendatang, saya ingin memastikan bahawa semua contoh kod masuk akal secara keseluruhan dan juga bahagiannya masing-masing. Saya akan berusaha untuk menamakan contoh-contoh saya secara konsisten dan memasukkannya ke dalam pakej sensikal.

Bahagian atas hierarki pakej saya adalah:

com.javaworld.media 

Setiap API atau topik yang saya tulis akan mempunyai sekurang-kurangnya satu bungkusan di bawah tahap teratas ini. Sebagai contoh, semua kod untuk artikel Java 2D ini akan berada di:

com.javaworld.media.j2d 

Oleh itu, untuk menggunakan aplikasi contoh pertama di Java 2D, anda akan memuat turun kod tersebut, memasukkannya ke dalam classpath anda, kemudian gunakan:

java com.javaworld.media.j2d.Contoh01 

(Sekiranya ruang nama terlalu panjang sesuai dengan keinginan anda atau atas sebab lain anda ingin menggunakan kod contoh tanpa perlu menggunakan nama yang memenuhi syarat, cukup komen baris pakej di awal setiap fail kod sumber.)

Saya akan menghasilkan fail Java Archive (jar) untuk contoh kod dan fail kelas setiap artikel. Arkib ini akan tersedia di Sumber setiap lajur, sekiranya anda ingin memuat turunnya dan melaksanakan contoh dari dalam arkib.

Saya juga akan menyimpan fail jar terkini yang mengandungi semua kod dan kelas dari lajur Pengaturcaraan Media semasa dan sebelumnya saya . Fail balang yang merangkumi semua ini akan tersedia di laman web peribadi saya.

Satu perkara terakhir mengenai contohnya: Saya telah memilih untuk membuat setiap contoh, kecuali saya menyatakan secara khusus sebaliknya, aplikasi atau applet yang berdiri sendiri. Ini akan menyebabkan pengulangan kod dari semasa ke semasa, tetapi saya rasa ia dapat mengekalkan integriti setiap contoh individu.

Cukup mengenai konvensyen. Mari mulakan pengaturcaraan dengan Java 2D!

Graphics2D: Kelas grafik yang lebih baik

Kelas pusat dalam Java 2D API adalah java.awt.Graphics2Dkelas abstrak, yang subkelas java.awt.Graphicsuntuk memperluas fungsi rendering 2D. Graphics2Dmenambah sokongan yang lebih seragam untuk manipulasi pelbagai bentuk, seperti membuat teks, garis, dan pelbagai bentuk dua dimensi lain yang setanding dengan kemampuan dan kegunaannya.

Mari kita mulakan dengan contoh mudah yang menunjukkan bagaimana anda mendapat dan menggunakan Graphics2drujukan.

Pakej 001 com.javaworld.media.j2d; 002 003 import java.awt. *; 004 import java.awt.event. *; 005 006 kelas awam Contoh01 memanjangkan Bingkai {007 / ** 008 * Menyalurkan objek Contoh01. 009 ** / 010 utama kekosongan statik awam (String args []) {011 baru Contoh01 (); 012} 013 014 / ** 015 * Pembina Contoh01 kami menetapkan ukuran bingkai, menambahkan komponen visual 016 *, dan kemudian menjadikannya dapat dilihat oleh pengguna. 017 * Ia menggunakan kelas penyesuai untuk menangani pengguna menutup 018 * bingkai. 019 ** / 020 awam Contoh01 () {021 // Tajuk bingkai kami. 022 super ("Java 2D Contoh01"); 023 024 // Tetapkan ukuran bingkai. 025 setSize (400,300); 026 027 // Kita perlu menghidupkan keterlihatan bingkai kita 028 // dengan menetapkan parameter Terlihat menjadi benar. 029 setVisible (benar); 030 031 // Sekarang,kami ingin memastikan kami membuang sumber dengan betul 032 // bingkai ini digunakan semasa tingkap ditutup. Kami menggunakan 033 // penyesuai kelas dalaman tanpa nama untuk ini. 034 addWindowListener (WindowAdapter baru () 035 {public void windowClosing (WindowEvent e) 036 {dispose (); System.exit (0);} 037} 038); 039} 040 041 / ** 042 * Kaedah cat memberikan keajaiban sebenar. Di sini kita 043 * menghantar objek Grafik ke Grafik2D untuk menggambarkan 044 * bahawa kita mungkin menggunakan keupayaan grafik lama yang sama dengan 045 * Grafik2D yang biasa kita gunakan dengan Grafik. 046 ** / 047 cat kosong awam (Grafik g) {048 // Berikut adalah cara kita melukis persegi dengan lebar 049 // 200, tinggi 200, dan bermula pada x = 50, y = 50. 050 g.setColor (Warna.red); 051 g.drawRect (50,50,200,200); 052 053 // Biarkan 's Tetapkan Warna menjadi biru dan kemudian gunakan objek Graphics2D 054 // untuk melukis sebuah segi empat tepat, diimbangi dari segi empat sama. 055 // Setakat ini, kami tidak melakukan apa-apa menggunakan Graphics2D yang 056 // kami juga tidak dapat menggunakan Graphics. (Kami sebenarnya 057 // menggunakan kaedah Graphics2D yang diwarisi dari Graphics.) 058 Graphics2D g2d = (Graphics2D) g; 059 g2d.setColor (Color.blue); 060 g2d.drawRect (75,75,300,200); 061} 062}

Semasa anda menjalankan Contoh01, anda akan melihat kotak merah dan segi empat biru, seperti yang ditunjukkan dalam gambar di bawah. Perhatikan bahawa terdapat masalah prestasi yang diketahui dengan versi Windows NT / 95 JDK 1.2 Beta 3 (pelepasan 1.2 terkini pada lajur ini). Sekiranya contoh ini perlahan pada sistem anda, anda mungkin perlu mengatasi bug seperti yang didokumentasikan dalam JavaWorld Java Tip 55 (lihat Sumber di bawah untuk tip ini).

Perhatikan bahawa sama seperti anda tidak membuat Graphicsobjek secara langsung , anda juga tidak membuat Graphics2Dobjek. Sebaliknya, runtime Java membina objek rendering dan meneruskannya ke paint()(baris 047 dalam senarai kod Contoh01), dan pada platform Java 1.2 dan seterusnya, objek ini juga menerapkan Graphics2Dkelas abstrak.

Setakat ini kami tidak melakukan sesuatu yang istimewa dengan kemampuan grafik 2D kami. Mari tambahkan beberapa kod pada akhir paint()kaedah contoh sebelumnya dan bawa beberapa ciri baru di Java 2D (Contoh02):

001 / ** 002 * Di sini kita menggunakan ciri Java 2D API baru seperti transformasi 003 * affine dan objek Shape (dalam hal ini 004 * satu, GeneralPath). 005 ** / 006 cat kosong awam (Grafik g) {007 g.setColor (Color.red); 008 g.drawRect (50,50,200,200); 009 010 Grafik2D g2d = (Grafik2D) g; 011 g2d.setColor (Color.blue); 012 g2d.drawRect (75,75,300,200); 013 014 // Sekarang, mari kita lukis satu lagi segi empat tepat, tetapi kali ini, mari kita 015 // gunakan GeneralPath untuk menentukannya segmen mengikut segmen. 016 // Selanjutnya, kita akan menterjemahkan dan memutar segiempat 017 // ini dengan Ruang Peranti (dan dengan itu, ke 018 // dua kuadrilateral pertama) menggunakan Transformasi Afin. 019 // Kami juga akan menukar warnanya. 020 Laluan GeneralPath = GeneralPath baru (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 di = AffineTransform baru (); 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 (jalan); 035}

Perhatikan bahawa kerana GeneralPathterdapat di dalam java.awt.geompakej, kita harus memastikan bahawa kita juga menambah baris import:

import java.awt.geom. *; 

Keluaran Contoh02 ditunjukkan dalam rajah berikut.

Java 2D memungkinkan untuk spesifikasi bentuk sewenang-wenang menggunakan java.awt.Shapeantara muka. Pelbagai bentuk lalai seperti segi empat tepat, poligon, garis 2D, dan lain-lain, melaksanakan antara muka ini. Salah satu yang paling menarik dari segi kelenturan adalah java.awt.geom.GeneralPath.

GeneralPaths membolehkan anda menerangkan jalan dengan bilangan tepi yang sewenang-wenang dan bentuk yang sangat kompleks. Dalam Contoh02, kami telah membuat sebuah segi empat tepat (garis 020-025), tetapi kami dengan mudah dapat menambahkan sisi atau sisi lain untuk membuat pentagon, atau heptagon, atau beberapa poligon pelbagai sisi yang lain. Perhatikan juga bahawa tidak seperti Graphicskod standard , Java 2D membolehkan kita menentukan koordinat menggunakan nombor titik terapung dan bukan bilangan bulat. Penjual CAD dunia, bergembira! Malah, Java 2D menyokong integer, doubledan floatingaritmetik di banyak tempat.

Anda mungkin juga menyedari bahawa ketika kita membuat jalan, kita melewati parameter GeneralPath.EVEN_ODD, ke dalam konstruktor (baris 020). Parameter ini mewakili peraturan penggulungan yang memberitahu penyaji bagaimana menentukan bahagian dalam bentuk yang ditentukan oleh jalan kami. Sila rujuk dokumentasi Java 2D javadoc yang dirujuk di Sumber untuk lebih lanjut mengenai peraturan penggulungan Java 2D.

Inovasi utama lain dalam Contoh02 berkisar pada penggunaan java.awt.geom.AffineTransforms (baris 027-031). Saya akan memberikan perincian perubahan tersebut kepada pembaca (lihat Sumber untuk artikel yang membincangkannya dengan lebih terperinci), tetapi cukup untuk mengatakan bahawa ini AffineTransformmembolehkan anda beroperasi pada mana-mana grafik Java 2D untuk menerjemahkan (memindahkan), memutarnya , skala, gunting, atau lakukan kombinasi manipulasi ini.

Kunci AffineTransformterletak pada konsep Ruang Peranti dan Ruang Pengguna . Ruang Peranti adalah kawasan di mana grafik akan diberikan pada layar. Ini serupa dengan koordinat yang digunakan ketika seseorang membuat Graphicsgrafik 2D berdasarkan gaya AWT biasa . Ruang Pengguna, bagaimanapun, adalah sistem koordinat berputar yang dapat diterjemahkan yang mungkin dikendalikan oleh satu atau lebih AffineTransforms.

Sistem koordinat Ruang Peranti dan Ruang Pengguna pada awalnya bertindih, dengan asal di kiri atas permukaan rendering (di sini, Bingkai). Paksi x positif bergerak tepat dari asal, manakala paksi y positif bergerak ke bawah.

Setelah transformasi pertama dalam Contoh02 (baris 028 dan 029), sistem koordinat Ruang Pengguna telah diputar 22.5 darjah berlawanan arah jarum jam berbanding Ruang Peranti. Kedua-duanya masih mempunyai asal usul yang sama. (Perhatikan bahawa putaran ditentukan dalam radian, dengan -PI / 8 radian sama dengan -22,5 darjah, atau 22,5 derajat CCW.) Sekiranya kita berhenti di sini dan melukis segi empat tepat, ia akan diputar di luar bidang pandangan kita di permohonan Frame.

Kami seterusnya menerapkan transformasi kedua (baris 030 dan 031), yang ini terjemahan, setelah putaran selesai. Ini menggerakkan sistem koordinat Ruang Pengguna berbanding dengan Ruang Peranti, menggesernya ke bawah unit 200.0 (apungan) dan 50.0 (apungan) kanan.

Apabila kita mengisi segi empat tepat hijau, ia diterjemahkan dan diputar relatif dengan Ruang Peranti.

Dari keluk Bezier dan tertib tinggi

Setelah kita mengkaji bagaimana transformasi dapat digunakan untuk memanipulasi objek grafik, mari kita kaji semula bagaimana kita membina bentuk sewenang-wenang yang kompleks dan menarik.

Lengkung digunakan di seluruh matematik dan grafik komputer untuk menghampiri bentuk kompleks dengan menggunakan bilangan titik matematik yang terbatas, jelas (dan idealnya kecil). Walaupun AWT standard tidak secara langsung menyokong gambar dengan lengkung sewenang-wenang pada masa lalu (platform Java 1.0 atau 1.1), Java 2D menambah sokongan bawaan untuk lengkung urutan pertama, kedua, dan ketiga. Anda boleh melengkung dengan dua titik akhir dan titik kawalan sifar, satu, atau dua . Java 2D menghitung lengkung urutan pertama dan kedua menggunakan formula linier dan kuadratik dan lengkungan kubik, atau urutan ketiga, menggunakan lengkung Bezier.

(Lengkung Bezier adalah jenis lengkung polinomial parametrik yang mempunyai beberapa sifat yang sangat diinginkan berkaitan dengan pengiraan lengkung dan permukaan tertutup. Mereka digunakan dalam banyak aplikasi grafik. Sila rujuk Sumber untuk maklumat lebih lanjut mengenai penggunaan polinomial parametrik dan lengkung Bezier dalam grafik komputer.) GeneralPathKaedah yang menarik setiap lengkung ini adalah:

  • lineTo() untuk segmen lurus (nyatakan titik akhir sahaja)
  • quadTo() untuk lengkung kuadratik (nyatakan satu titik kawalan)
  • curveTo() untuk lengkung tertib ketiga (nyatakan dua titik kawalan, dilukis menggunakan lengkung Bezier kubik)