Memulai dengan Java 2D

Java 2D API adalah API platform Java 1.2 inti (lihat Sumberdaya untuk berbagai informasi tentang API dan implementasinya). Implementasi API tersedia sebagai bagian dari Java Foundation Classes (JFC) dalam rilis beta Sun JDK untuk Windows NT / 95 dan Solaris saat ini. Saat Java 1.2 diselesaikan, Java 2D harus tersedia di lebih banyak platform.

Perhatikan bahwa meskipun Java 2D telah dikembangkan secara terpisah dari bagian lain JFC, itu tetap merupakan bagian inti dari 1.2 AWT. Kami akan membuat perbedaan dan menunjukkan fitur-fitur khusus 2D untuk diskusi, tetapi Anda harus ingat bahwa fungsionalitas ini sama pentingnya dengan grafik 1.2 seperti dukungan AWT 1.0 dan 1.1 yang lama.

Java 2D memperluas mekanisme AWT sebelumnya untuk menggambar grafik 2D, memanipulasi teks dan font, memuat dan menggunakan gambar, serta menentukan dan menangani warna dan ruang warna. Kami akan mengeksplorasi mekanisme baru ini di kolom ini dan kolom mendatang.

Catatan tentang nomenklatur dan konvensi

Untuk kolom ini, platform pengembangan utama saya adalah PC yang menjalankan Windows 95 atau Windows NT. Saya berharap dapat memberikan tip dan trik khusus platform lainnya jika memungkinkan, tetapi saya akan fokus pada Windows karena di situlah saya akan menghabiskan sebagian besar waktu saya.

Ketika saya menulis nama metode, itu harus selalu dalam bentuk methodname(). Tanda kurung di belakang dimaksudkan untuk membedakan ini sebagai metode. Metode ini mungkin menggunakan parameter atau tidak. Dalam praktiknya, konteksnya harus selalu menjelaskan hal ini.

Daftar kode sumber akan diberikan dengan nomor baris disertakan. Saya berencana menggunakan nomor baris untuk referensi silang teks artikel dan daftar kode yang sesuai. Ini juga akan memudahkan Anda untuk membuat anotasi kolom, jika Anda memilih untuk mencetak salinan. Harap dicatat, bagaimanapun, bahwa file sumber yang ditautkan dari kolom adalah file * .java biasa (tanpa nomor baris) sehingga Anda dapat mengunduh dan mengembangkannya.

Karena saya akan menulis tentang banyak API Media dan Komunikasi dalam beberapa bulan mendatang, saya ingin memastikan bahwa semua kode contoh masuk akal secara keseluruhan dan juga di masing-masing bagian. Saya akan mencoba untuk secara konsisten memberi nama contoh saya dan menempatkannya ke dalam paket yang masuk akal.

Bagian atas hierarki paket saya adalah:

com.javaworld.media 

Setiap API atau topik yang saya tulis akan memiliki setidaknya satu sub-paket di bawah level teratas ini. Misalnya, semua kode untuk artikel Java 2D ini akan berada di:

com.javaworld.media.j2d 

Jadi, untuk menjalankan aplikasi contoh pertama pada Java 2D, Anda harus mengunduh kodenya, meletakkannya di jalur kelas Anda, lalu gunakan:

java com.javaworld.media.j2d.Example01 

(Jika namespace terlalu panjang untuk Anda sukai atau karena alasan lain Anda ingin menggunakan kode contoh tanpa harus menggunakan nama yang sepenuhnya memenuhi syarat, cukup beri komentar pada baris paket di awal setiap file kode sumber.)

Saya akan menghasilkan file Java Archive (jar) untuk setiap kode contoh artikel dan file kelas. Arsip ini akan tersedia di Sumberdaya setiap kolom, jika Anda ingin mengunduhnya dan menjalankan contoh dari dalam arsip.

Saya juga akan menyimpan file jar up-to-date yang berisi semua kode dan kelas dari kolom Pemrograman Media saya saat ini dan sebelumnya . File jar yang mencakup semua ini akan tersedia di situs web pribadi saya.

Satu poin terakhir pada contoh: Saya telah memilih untuk membuat setiap contoh, kecuali saya secara khusus mencatat sebaliknya, aplikasi atau applet yang berdiri sendiri. Ini akan menyebabkan beberapa pengulangan kode dari waktu ke waktu, tetapi saya merasa itu paling baik menjaga integritas masing-masing contoh.

Cukup tentang konvensi. Mari mulai pemrograman dengan Java 2D!

Graphics2D: Kelas Grafik yang lebih baik

Kelas utama dalam Java 2D API adalah java.awt.Graphics2Dkelas abstrak, yang merupakan subkelas java.awt.Graphicsuntuk memperluas fungsionalitas rendering 2D. Graphics2Dmenambahkan dukungan yang lebih seragam untuk manipulasi berbagai bentuk, yang membuat teks, garis, dan segala macam bentuk dua dimensi lainnya sebanding dalam kemampuan dan kegunaannya.

Mari kita mulai dengan contoh sederhana yang menunjukkan bagaimana Anda mendapatkan dan menggunakan Graphics2dreferensi.

001 paket com.javaworld.media.j2d; 002 003 import java.awt. *; 004 import java.awt.event. *; 005 006 kelas publik Example01 memperluas Frame {007 / ** 008 * Membuat instance objek Example01. 009 ** / 010 public static void main (String args []) {011 new Example01 (); 012} 013 014 / ** 015 * Konstruktor Example01 kami menyetel ukuran bingkai, menambahkan komponen visual 016 *, lalu membuatnya terlihat oleh pengguna. 017 * Ini menggunakan kelas adaptor untuk menangani pengguna yang menutup 018 * bingkai. 019 ** / 020 public Example01 () {021 // Beri judul frame kita. 022 super ("Java 2D Example01"); 023 024 // Atur ukuran bingkai. 025 setSize (400.300); 026 027 // Kita perlu mengaktifkan visibilitas frame 028 // dengan mengatur parameter Visible menjadi true. 029 setVisible (benar); 030 031 // Sekarang,kami ingin memastikan bahwa kami membuang sumber daya dengan benar 032 // frame ini digunakan saat jendela ditutup. Kami menggunakan 033 // adaptor kelas dalam anonim untuk ini. 034 addWindowListener (new WindowAdapter () 035 {public void windowClosing (WindowEvent e) 036 {dispose (); System.exit (0);} 037} 038); 039} 040 041 / ** 042 * Metode melukis memberikan keajaiban yang sesungguhnya. Di sini kami 043 * mentransmisikan objek Grafik ke Grafik2D untuk mengilustrasikan 044 * bahwa kami dapat menggunakan kemampuan grafik lama yang sama dengan 045 * Grafik2D yang biasa kami gunakan dengan Grafik. 046 ** / 047 public void paint (Grafik g) {048 // Berikut adalah cara kami menggambar persegi dengan lebar 049 // of 200, tinggi 200, dan mulai dari x = 50, y = 50. 050 g.setColor (Color.red); 051 g. Penarikan (50,50,200,200); 052 053 // Biarkan 's atur Color menjadi biru dan kemudian gunakan objek Graphics2D 054 // untuk menggambar persegi panjang, offset dari persegi. 055 // Sejauh ini, kami tidak melakukan apapun menggunakan Graphics2D yang 056 // kami juga tidak dapat menggunakan Grafik. (Kami sebenarnya 057 // menggunakan metode Graphics2D yang diwarisi dari Graphics.) 058 Graphics2D g2d = (Graphics2D) g; 059 g2d.setColor (Color.blue); 060 g2d.drawRect (75,75,300,200); 061} 062}

Saat Anda menjalankan Example01, Anda akan melihat kotak merah dan persegi panjang biru, seperti yang ditunjukkan pada gambar di bawah. Perhatikan bahwa ada masalah kinerja yang diketahui dengan versi Windows NT / 95 dari JDK 1.2 Beta 3 (rilis 1.2 terbaru pada kolom ini). Jika contoh ini sangat lambat pada sistem Anda, Anda mungkin perlu mengatasi bug seperti yang didokumentasikan di JavaWorld Java Tip 55 (lihat Sumberdaya di bawah untuk tip ini).

Perhatikan bahwa sama seperti Anda tidak membuat Graphicsinstance objek secara langsung , Anda juga tidak membuat instance Graphics2Dobjek. Sebaliknya, runtime Java membangun objek rendering dan meneruskannya ke paint()(baris 047 dalam daftar kode Example01), dan pada platform Java 1.2 dan seterusnya, objek ini mengimplementasikan Graphics2Dkelas abstrak juga.

Sejauh ini kami belum melakukan sesuatu yang istimewa dengan kemampuan grafis 2D kami. Mari tambahkan beberapa kode di akhir paint()metode contoh sebelumnya dan masukkan beberapa fitur baru ke Java 2D (Example02):

001 / ** 002 * Di sini kita menggunakan fitur Java 2D API baru seperti affine 003 * transformasi dan objek Bentuk (dalam hal ini 004 * satu generik, GeneralPath). 005 ** / 006 cat ruang kosong publik (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 menggambar persegi panjang lain, tapi kali ini, 015 // gunakan GeneralPath untuk menentukan segmen demi segmen. 016 // Selanjutnya, kita akan menerjemahkan dan memutar persegi panjang 017 // ini relatif terhadap Device Space (dan dengan demikian, ke 018 // dua segiempat pertama) menggunakan AffineTransform. 019 // Kami juga akan mengubah warnanya. 020 GeneralPath path = new 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 pada = 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 (jalur); 035}

Perhatikan bahwa karena GeneralPathterletak di dalam java.awt.geompaket, kita perlu memastikan bahwa kita juga menambahkan baris impor:

import java.awt.geom. *; 

Output dari Example02 ditunjukkan pada gambar berikut.

Java 2D memungkinkan spesifikasi bentuk arbitrer menggunakan java.awt.Shapeantarmuka. Berbagai bentuk default seperti persegi panjang, poligon, garis 2D, dll., Terapkan antarmuka ini. Salah satu yang paling menarik dari segi fleksibilitas adalah java.awt.geom.GeneralPath.

GeneralPaths memungkinkan Anda mendeskripsikan jalur dengan jumlah tepi yang berubah-ubah dan bentuk yang berpotensi sangat kompleks. Dalam Example02, kita telah membuat persegi panjang (garis 020-025), tetapi kita dapat dengan mudah menambahkan sisi atau sisi lain untuk membuat segi lima, atau segi tujuh, atau poligon banyak sisi lainnya. Perhatikan juga bahwa tidak seperti Graphicskode standar , Java 2D memungkinkan kita untuk menentukan koordinat menggunakan bilangan floating-point, bukan bilangan bulat. Vendor CAD dunia, bersukacitalah! Bahkan, Java 2D mendukung integer, doubledan floatingaritmatika di banyak tempat.

Anda mungkin juga memperhatikan bahwa saat kami membuat jalur, kami meneruskan parameter GeneralPath.EVEN_ODD,, ke konstruktor (baris 020). Parameter ini mewakili aturan berliku yang memberi tahu perender cara menentukan bagian dalam bentuk yang ditentukan oleh jalur kita. Silakan merujuk ke dokumentasi javadoc 2D Java yang direferensikan di Sumber Daya untuk mengetahui lebih lanjut tentang aturan putaran 2D Java.

Inovasi besar lainnya di Example02 berkisar penggunaan java.awt.geom.AffineTransforms (baris 027-031). Saya akan menyerahkan secara spesifik transformasi semacam itu kepada pembaca (lihat Sumber untuk artikel yang membahas ini secara lebih rinci), tetapi cukup untuk mengatakan bahwa AffineTransformitu memungkinkan Anda untuk beroperasi pada grafik Java 2D apa pun untuk menerjemahkan (memindahkan), memutarnya , skalakan, geser, atau lakukan kombinasi manipulasi ini.

Kuncinya AffineTransformterletak pada konsep Device Space dan User Space . Device Space adalah area tempat grafik akan ditampilkan di layar. Ini analog dengan koordinat yang digunakan ketika seseorang membuat Graphicsgrafik 2D berbasis gaya AWT biasa . Ruang Pengguna, bagaimanapun, adalah sistem koordinat yang dapat diterjemahkan dan dapat diputar yang dapat dioperasikan oleh satu atau lebih AffineTransforms.

Sistem koordinat Ruang Perangkat dan Ruang Pengguna awalnya tumpang tindih, dengan asal di kiri atas permukaan rendering (di sini, Bingkai). Sumbu x positif bergerak ke kanan dari asalnya, sedangkan sumbu y positif bergerak ke bawah.

Setelah transformasi pertama di Example02 (baris 028 dan 029), sistem koordinat Ruang Pengguna telah diputar 22,5 derajat berlawanan arah jarum jam relatif ke Ruang Perangkat. Keduanya masih memiliki asal yang sama. (Perhatikan bahwa rotasi ditentukan dalam radian, dengan -PI / 8 radian sama dengan -22,5 derajat, atau 22,5 derajat CCW.) Jika kita berhenti di sini dan menggambar persegi panjang, sebagian besar akan diputar keluar dari bidang pandang kita di aplikasi Frame.

Kami selanjutnya menerapkan transformasi kedua (baris 030 dan 031), yang ini terjemahan, setelah rotasi selesai. Ini memindahkan sistem koordinat Ruang Pengguna relatif terhadap Ruang Perangkat, menggesernya ke bawah 200,0 unit (pelampung) dan ke kanan 50,0 (pelampung) unit.

Saat kita mengisi persegi panjang hijau, itu diterjemahkan dan diputar relatif terhadap Ruang Perangkat.

Kurva Bezier dan lebih tinggi

Sekarang kita telah memeriksa bagaimana transformasi dapat digunakan untuk memanipulasi objek grafis, mari kita periksa kembali bagaimana kita membangun bentuk arbitrer yang kompleks dan menarik.

Kurva digunakan di seluruh matematika dan grafik komputer untuk memperkirakan bentuk kompleks menggunakan sejumlah titik matematika yang terbatas, terdefinisi dengan baik (dan idealnya kecil). Sementara AWT standar tidak secara langsung mendukung gambar dengan kurva arbitrer di masa lalu (platform Java 1.0 atau 1.1), Java 2D menambahkan dukungan bawaan untuk kurva urutan pertama, kedua, dan ketiga. Anda dapat menggambar kurva dengan dua titik akhir dan nol, satu, atau dua titik kontrol . Java 2D menghitung kurva urutan pertama dan kedua menggunakan rumus linier dan kuadrat serta kurva kubik, atau urutan ketiga, menggunakan kurva Bezier.

(Kurva Bezier adalah jenis kurva polinomial parametrik yang memiliki beberapa properti yang sangat diinginkan terkait dengan perhitungan permukaan dan kurva tertutup. Mereka digunakan dalam berbagai aplikasi grafik. Silakan merujuk ke Sumber untuk informasi lebih lanjut tentang penggunaan polinomial parametrik dan kurva Bezier dalam grafik komputer.) GeneralPathMetode yang menggambar masing-masing kurva ini adalah:

  • lineTo() untuk segmen lurus (tentukan hanya titik akhir)
  • quadTo() untuk kurva kuadrat (tentukan satu titik kontrol)
  • curveTo() untuk kurva urutan ketiga (tentukan dua titik kontrol, digambar menggunakan kurva Bezier kubik)