secangkir kopi java
JAVA 2 STANDARD EDITION

Oleh: Galih Satria

Copyright © Agustus 2004

expressed or implied. . with regrad to these programs or to the documentation contained in this book.All rights reserved. You may only use this book for private study. scolarship. The author makes no warranty of any kind. or research. Not for commercial use.

Pengantar

Sudah lama Aku ingin mengumpulkan hasil dari petualanganku dengan Java yang sudah berjalan hampir setahun. Ini bukanlah sebuah buku tutorial atau apa – Aku belum pantas menulis buku-buku semacam itu. Ini hanyalah semacam buku harian yang menceritakan waktu yang kuhabiskan untuk bercengkerama dengan Java. Aku sudah bosan menulis buku harian yang berjudul “Gadis-Gadis yang Pernah Kutaksir” karena mereka hanyalah membuat luka-luka kecil tanpa membuat seorang Fatso berbahagia. Aku ingin sesuatu yang baru. Tujuanku menulis buku harian ini adalah semata-mata agar kesulitan-kesulitanku ketika bergaul dengan Java tidak terjadi pada kamu. Ketika Aku mendapat kesulitan dan masalah ketika mengerti sifatsifat Java, tidak ada yang bisa kutanyai. Aku hanya mendapatkan masukan dari buku, forum di internet, dan situs resmi Java sendiri di http://java.sun.com. Bahkan buku yang berbahasa Indonesiapun tak ada yang memuaskanku. Aku mencoba menulis ini agar kesulitanku dulu tercatat secara rapi (cieeee). Ini bukanlah buku harian tentang Bahasa Berorientasi Objek tetapi buku harian tentang Java. Jadi jika kamu mengharapkan ada pembahasan konsep inheritance, polimorfisme, overloading, overriding dan semacamnya, harapan itu hanyalah akan menjadi harapan kosong belaka. Juga maaf buat yang belum mengerti struktur bahasa Java babar blas, aku mengasumsikan kamu sudah pernah membuat aplikasi Java yang sederhana. Aku mengasumsikan kamu sudah pernah menulis program Hello World dengan bahasa Java.

Isi Buku Ini Bab I: Membahas tentang bagaimana membuat sebuah antar muka pemakai (User Interface) dengan menggunakan komponen Swing. Kita
Pengantar

i

akan membuat sebuah Internet Explorer sederhana di situ. Kenapa aku memakai Swing dan bukan AWT? Karena AWT sudah kuno! Hehehe…

Bab 2: Membahas Swing tingkat lanjut. Kita akan membahas konsep Model-View Controller di sana. Kita akan mempelajari bagaimana mengolah data dan menampilkannya secara terpisah dengan komponen JList, JTable, dan JTree.

Bab 3: Membahas tentang bagaimana membuat koneksi ke database dengan Java. Kita akan mempelajari teknologi Java yang disebut Java Database Connectivity (JDBC). Kita juga akan membahas sedikit konsep tentang Basis Data di sana, termasuk Structured Query Language (SQL), Data Definition Language (DDL), dan Data Manipulation Language (DML).

Bab 4: Mendalami konsep JDBC dengan lebih dalam lagi. Kita akan membuat aplikasi Buku Alamat. Kita akan memulai dengan membuat database dengan MySQL, kemudian baru menyusun dan merangkai kode-kode Java satu per satu. Aku akan mengacungkan 3 jempol kalau kamu membaca buku ini hingga bab ini. Aku akan berkata hebat! Hehehe.. bukan apa-apa, soalnya tidak banyak orang yang suka membaca kode-kode Java yang njlimet. Appendix A: Membahas tentang Java Archive (JAR), file yang digunakan untuk mendistribusikan aplikasi Java. Kita tidak akan membahas secara detail tentang JAR, hanya sekedar untuk mengetahui dasar-dasarnya aja. Namanya juga Appendix… Appendix B: Jika kamu new-bie, tetapi sudah mengenal dasar bahasa Java, mungkin kamu perlu membaca ini dulu. Appendix B membahas bagaimana menset J2SDK kita agar bekerja dengan baik, lalu kubahas sedikit tentang packaging di Java, dan beberapa editor Java yang kurekomendasikan.

ii

Secangkir Kopi Java

Apa yang tertuang dalam buku harian ini hanyalah sebagian kecil dari teknologi Java. Dalam suatu topik, aku tidak bisa menjelaskan semua detail yang dimilikinya, meskipun aku berusaha membahas secara lebih mendetail daripada buku-buku berbahasa Indonesia yang pernah kubaca, dengan risiko kamu yang masih new-biee terhadap Java akan sedikit kebingungan. Tapi nggak usah berkecil hati, ada orang yang memulai sesuatu tidak selalu dari awal, tetapi dari yang sulit dulu. Jika kamu masih merasa kurang tentang Java, bukalah internet. Bagiku, internet adalah sumber ilmu tiada batas. Banyak hal tentang Java di sana, baik untuk yang baru membaca Java hari ini maupun yang sudah veteran dalam ber-coding dan di Java. Google Aku merekomendasikan

http://java.sun.com, sebagai acuannya.

mbah

(http://www.google.com)

Oke itu aja, akhir kata kuucapkan Met Ber-Jave Ria! Nuwun inggih para sederek kula sedaya….. ( ini mah Jawa bukan Java )

Tulungagung tercinta, Liburan Juni – Agustus 2004

Galih ‘f4tso’ Satria

Pengantar

iii

........23 i.......................................................92 First Run! ... Database Design ..................96 Koneksi Database .....................................................................................................145 Class-Class Pendukung ...............................................121 Class MySQLAccess ............................................Daftar Isi Pengantar ..20 Model .7 i................................ JList............................................................................................................92 Driver JDBC..................25 Advanced JList........................ JTree...................81 i.....................................................................................80 Java Database Connectivity [ JDBC ] ................................70 i......................................................................................... JTable................................................................................................................................130 Memperkenalkan.................................................................. Swing Action .83 Structured Query Language ( SQL ) ..............................................................................................................43 iii.......................................................................15 Kotak Konfirmasi ( Confirm Dialog ) ....................................140 Membangun User Interface Utama: Class AddressBook.......................83 ii...............................................................................................63 Tree Cell Renderer dan Tree Cell Editor ..10 iii........................122 User Interface I: Class InsertForm ............................. GridBagLayout............................................................................. Sekilas Database........38 Advanced JTable.................................i Daftar Isi .............3 ii..................................99 ResultSet ........................98 Statement ........................................................................................................................................................................................................................................................................................68 Tree Event...................... Class JOptionPane...117 Class AddressEntry ................................................................................................111 i.....................17 Kotak Input / Input Dialog.......................................................................................................................................... iv Java GUI ( Graphical User Interface ) ...............................................................swing ............................101 Studi Kasus JDBC – Address Book .................................................61 First Run! ..................................114 iii..........33 ii................................................................. Java Database Connectivity.......................................................................View Controller ..................................................................................113 ii..... Menampilkan Dialog Box .................................................................15 Message Box ...........................................................................................................................................................................................117 Interface DataAccess .........................................................................154 iv Secangkir Kopi Java .....151 iv............................. Ringkasan ... Penulisan Kode Program dengan Java .......1 JToolBar – Toolbar pada javax........................................................................................................139 Membangun User Interface II: Class ViewPane................................... Web Browser – Implementasi JEditorPane dan JToolBar ......................... Instalasi Database dan Pembuatan Database ............................................................................................ Ringkasan ..............................................................

............ 169 Pengantar v ................................................................. 165 Au’ Revoir! ............................Appendix A – Mendistribusikan Aplikasi Java dengan JAR ................................................................................. 167 Daftar Pustaka ............ 159 Menjalankan Aplikasi yang Dibundel dalam JAR ..................................... 155 Membuat File JAR ............................................................ 164 Integrated Development Environment .............. 157 Perintah JAR Lainnya ............................................................................................................................ 159 Appendix B ......................................................................... 161 Tentang Packaging......Instalasi J2SDK dan Tentang Packaging ................................................................

.

java gui ( graphical user interface ) Pertemuan Pertamaku dengan Java. Oktober 2003 .

.

*. Java GUI (Graphical User Interface) 1 . import java.util. kita merequest file HTML dari web server dan menampilkannya di JEditorPane. private int historyIndex.net. jika kita ingin membuat sebuah web browser yang kokoh. Saudaranya adalah JTextArea dan JTextField.i. class yang digunakan untuk merender teks yang sedang diedit ataupun dilihat. Selesai! /************************************** * Simple WebBrowser to Understand * * Swing Components * * Written by : fatso – 081103 * **************************************/ package WebBrowser. disarankan tidak memakai JEditorPane karena masih buggy – banyak terdapat bug.io. import javax. //konstruktor public WebBrowserPane () { //disable mengedit JEditorPane untuk mengenable //hyperlinks setEditable ( false ). import java.1 – Class WebBrowserPane sebagai subclass dari JEditorPane. Kamu harus membuat panel tersendiri untuk memparsing dan merender file HTML dengan baik.*.*. import java.*. public class WebBrowserPane extends JEditorPane { private List history = new ArrayList(). JEditorPane bisa merender sebuah file HTML sehingga kita bisa membuat sebuah web browser sederhana. Meskipun demikian. untuk menampilkan halaman HTML pada aplikasi kita. Web Browser – Implementasi JEditorPane dan JToolBar 08 November 2003 – ketika dunia terasa hampa JEditorPane adalah sub class dari class JTextComponent. } Listing 1.swing. Ide dari web browser ini sangat sederhana.

return url. } //displayPage method.. historyIndex = history. Method goToURL( URL url ) akan menampilkan URL pada JEditorPane dengan method setPage ( URL pageURL ) dan memodifikasi historyIndex untuk kebutuhan back.. } //display next url public URL forward () { historyIndex++. Listing 1. 2 Secangkir Kopi Java .size() . public URL back () { historyIndex--.//display u-er-el... history. URL url = ( URL ) history. history. } } } < 0 ) 0. Konstruktor akan menset JEditorPane menjadi tidak bisa diedit agar hyperlink file HTML bisa aktif.get ( historyIndex ).printStackTrace (). WebBrowserPane ini adalah subclass dari JEditorPane. if ( historyIndex >= history.. } //display previous history. public void goToURL ( URL url ) { displayPage ( url ). ). untuk menampilkan halaman HTML pada aplikasi kita.1. if ( historyIndex historyIndex = URL url = ( URL ) displayPage ( url return url.add ( url ).1. private void displayPage ( URL pageURL ) { try { setPage ( pageURL ).get ( historyIndex )..1 – Class WebBrowserPane sebagai subclass dari JEditorPane. } catch ( IOException ex ) { ex. Di sini kita menambahkan kemampuan JEditorPane untuk mengambil file HTML dari web server.size() . displayPage ( url ).size() ) historyIndex = history.

yang bertindak sebagai toolbar pada aplikasi web browser kita. Method forward() akan mengincrement historyIndex. Namun di sini.swing Toolbar adalah kumpulan button-button kecil-kecil. padahal ini adalah pertemuan pertamaku dengan Java dan langsung jatuh cinta. Java GUI (Graphical User Interface) 3 .*.*. biasanya letaknya di bawah menu dari suatu aplikasi. Cinta pada pandangan pertama? Aku selalu mengalami itu! JToolBar – Toolbar pada javax. Hmm… tertarik? Let’s go baby! package WebBrowser. Kita bisa aja langsung memasang toolbar tanpa harus mensubclass-kan JToolBar.2 – Class WebToolBar.swing. Aku biasanya memakai JButton untuk kupasang di Toolbar. Gimana? Nggak bingung kan? Aku aja dulu nggak bingung kok. untuk membiasakan diri dengan konsep inheritance. historyIndex di sini berfungsi sebagai semacam pointer yang menunjuk ArrayList.event.event. import java. import javax. Listing 1.awt. import java.swing. hanya icon kecil yang biasanya kuambil dari icon-iconnya KDE Linux. kita akan men-subclass-kan JToolBar.Method forward() akan mengambil URL dari ArrayList dan menampilkannya pada WebBrowserPane.*. Dan button itu tidak kuberi teks. import java.*. method displayPage ( URL pageURL ) adalah method yang bertugas untuk menampilkan URL pada JEditorPane.awt. import javax.*. Dan terakhir. subclass dari JToolBar. Method back() adalah kebalikan dari method forward().net.

getResource ( "images/undo. subclass dari JToolBar. //buat back button backButton = new JButton ( new ImageIcon ( getClass(). //konstruktor public WebToolBar( WebBrowserPane browser ) { super ( "Web Navigator" ). } catch ( MalformedURLException mue ) { mue. urlTextField.printStackTrace ().public class WebToolBar extends JToolBar implements HyperlinkListener { private WebBrowserPane webBrowserPane. private JButton forwardButton.getText () ). urlTextField = new JTextField ( 25 ). private JButton backButton.2 – Class WebToolBar. webBrowserPane.addActionListener ( new ActionListener () { public void actionPerformed( ActionEvent event ) { try { URL url = new URL ( urlTextField. 4 Secangkir Kopi Java .png" ) ) ). //registering webBrowserPane = browser. Listing 1.addHyperlinkListener ( this ). } } } ). webBrowserPane. yang bertindak sebagai toolbar pada aplikasi web browser kita. private JTextField urlTextField.goToURL ( url ).

setText ( url.getURL ().addActionListener ( new ActionListener () { public void actionPerformed( ActionEvent event ) { URL url = webBrowserPane.toString () ).EventType.toString () ).toString () ).addActionListener ( new ActionListener () { public void actionPerformed( ActionEvent event ) { URL url = webBrowserPane. subclass dari JToolBar. urlTextField.setText ( url. forwardButton. } }). //buat next button forwardButton = new JButton ( new ImageIcon ( getClass(). //add button to toolbar add ( backButton ).backButton. urlTextField.getResource ( "images/redo. } } } Listing 1.getEventType () == HyperlinkEvent.setText ( url. add ( forwardButton ).forward (). } }). yang bertindak sebagai toolbar pada aplikasi web browser kita.goToURL ( url ).ACTIVATED ) { URL url = event.2 – Class WebToolBar. Java GUI (Graphical User Interface) 5 .png" ) ) ). webBrowserPane.back (). } //hyperlink events public void hyperlinkUpdate( HyperlinkEvent event ) { if ( event. urlTextField. add ( urlTextField ).

Langkah selanjutnya adalah memasang button-button tersebut pada toolbar. Dia juga akan mempersenjatai dirinya agar bisa mendengarkan hyperlink ketika diklik. tetapi praktis dan ekonomis. Sekarang tinggal memberi sentuhan akhir. Method add ( JComponent component ) adalah method asli milik JToolBar. jadilah monyet! Ini dia launcher code-nya: 6 Secangkir Kopi Java . mbah canggah dari JToolBar. Button back kita beri aksi untuk memanggil method back() dan menset urlTextField dengan URL yang sesuai pada return value method back(). Tugasnya adalah memanggil method goToURL dengan URL yang tercantum pada urlTextField. compile. Button-button tersebut langsung kita beri icon dari resource yang ada. Sekarang kita akan membangun button-button. dia akan memanggil method forward. Kita gabungkan dua class di atas dalam satu window. urlTextField kita beri ActionListener.Konstruktor WebToolBar akan memanggil mbahnya untuk memberi judul. kita ambil URL-nya dan kemudian kita tampilkan pada JEditorPane. Sedikit membingungkan memang. yaitu membuat launcher code-nya. Button forward kita beri perlakuan yang mirip dengan button back. Lebih tepatnya miliknya JComponent. Ketika suatu hyperlink diaktivasi ( diklik ). JEditorPane sudah kita set bisa membaca hyperlink. sim salabim…. Gaya menambahkan action listener seperti ini namanya anonymous class.. Bedanya. Langkah terakhir adalah menentukan jalannya program ketika suatu hyperlink diklik.

*. import javax. contentPane. contentPane. 480 ).2 ) Tak ada yang istimewa di sini. private WebBrowserPane browserPane.awt. browser.event.event. browser. browser.setSize ( 640.swing.*.swing. public class WebBrowser extends JFrame { private WebToolBar toolBar.setDefaultCloseOperation ( EXIT_ON_CLOSE ). import javax. BorderLayout. Container contPane adalah kanvas dasar pada window kita tempat kita memasang komponen- Java GUI (Graphical User Interface) 7 .net.3 – Class WebBrowser. BorderLayout.setVisible ( true ).CENTER ). browserPane = new WebBrowserPane ().add ( toolBar. } public static void main( String[] args ) { WebBrowser browser = new WebBrowser (). toolBar = new WebToolBar ( browserPane ). import java. import java. yang mengumpulkan dua class yang telah kita tulis sebelumnya ( Listing 1.package WebBrowser. } } Listing 1.*.add ( new JScrollPane ( browserPane ). kode peluncur dari aplikasi web browser kita.*. Container contentPane = getContentPane ().awt. import java.1 dan 1.NORTH ). //konstruktor public WebBrowser() { super ( "Fatso Internet Explorer" ).*.

CLASSPATH. Terus terang dulu aku bingung setengah mati karena selalu ada eksepsi “NoClassDefFoundError”.WebBrowser Baca bismillah dulu dan inilah hasilnye….WebToolBar javac –d c:\classes WebBrowser. Kita akan mengkompilasi WebBrowserPane dengan command Windows: javac –d c:\classes WebBrowser. Aku yakin kamu sudah bisa bagaimana meng-compile file java yang ada packagenya. Ayo diCompile! Di sini aku mengansumsikan kamu sudah master dalam hal setting PATH. masukkan aja ke JCreator atau JBuilder atau IDE yang lain. Swing sudah melakukan hal itu semua untuk kita. program langsung memanggil System. setDefaultCloseOperation ( EXIT_ON_CLOSE ) artinya ketika window di-close. Agar bisa nye-croll. Kalau belum. baca Appendix B yang ada di akhir buku ini. Kemudian. Jika masih bingung.WebBrowserPane Parameter –d adalah kita mendefinisikan direktori output dari hasil kompilasi di direktori C:\classes di Windows atau di /home/fatso/classes di UNIX. Direktori ini harus masuk dalam CLASSPATH agar javac bisa mengenali hasil kompilasi kita. compile WebToolBar dan WebBrowser berturut-turut dengan perintah: javac –d c:\classes WebBrowser. 8 Secangkir Kopi Java . dan segala tetek bengek lainnya. Jika kita memakai AWT ( Abstract Window Toolkit ) kita perlu meng- override window event agar bisa keluar.exit ( 0 ).komponen.WebBrowserPane UNIX: javac –d /home/fatso/classes WebBrowser. WebBrowserPane kita masukkan pada JScrollPane. Mmmm…….

karena berbeda dengan teks editor manapun.java WebBrowser. Dia hanya bisa menerima file HTML murni. yang kugunakan untuk menampilkan jendela help. WebBrowser ini kuntegrasikan pada teks editorku.WebBrowser Sudah kukatakan JEditorPane masih buggy.0. sangat menghargai karyaku itu. Jadilah webku yang rusak itu.html.1 – Tampilan dari web browser ( URL: http://localhost/galihsatria/index. Contoh file HTML pada gambar itu memakai CSS sebagai text formatternya dan si JEditorPane tidak bisa membacanya. lokasi penggodokan situs resmi Galih Satria versi 2. Aku senang sekali karena Pak Arun. dosenku. Tapi bisa kamu coba dengan sebuah file HTML yang sederhana dan lihat hasilnya… tidak terlalu mengecewakan kok. Gambar 1. karena jendela help-nya bisa untuk membuka Yahoo! Java GUI (Graphical User Interface) 9 .1 ). tugas akhir kuliah BPL.

Ketiga komponen itu memiliki aksi sendiri-sendiri. import java. Heh… dowone ceramahku…. dan Button." ). misalnya. Perintah untuk meng-cut bisa kita masukkan ke Action tersebut.*. Toolbar. Ketika pop up menu cut.. demonstrasi Action dalam aplikasi berbasis Java. Swing action Grapical User Interface ( GUI ) paling tidak memiliki tiga komponen utama.*. Kita membuat menu edit cut. toolbar cut.awt. public class SwingActions extends JFrame { //instans private Action loveAction. Ribet buanget wis… Swing mengatasi kesulitan itu dengan membuat class Action.4 – Class SwingAction. Misalnya. untuk mempermudah manajemen Event Handler 10 Secangkir Kopi Java . Menu.swing.ii. Listing 1.event. dsb..awt.*. loveAction = new LoveAction (). kita memiliki method Cut untuk menghapus teks dan mengirimnya ke Clipboard. kita tak perlu mengurusi komponen lain yang berhubungan dengan cut. Namun sering sekali kita mendesain ketiga komponen tersebut menjalankan hal yang sama. //konstruktor public SwingActions() { super ( "Action Deeh. mendisabled dirinya karena tak ada yang bisa di-cut. Langsung ajah ke kodenya yach! import java. Dan kita mesti membuat action listener untuk masing-masing komponen secara terpisah. kita cukup mendisabled Action cut dan semua komponen yang merujuk Action cut akan terdisabled secara ostosmastis. Dan seluruh komponen kita rujuk ke Action tersebut. import javax. private Action exitAction. pop up menu cut. exitAction = new ExitAction ().

//bikin menu JMenu fileMenu = new JMenu ( "File" ). BorderLayout. //bikin toolbar JToolBar toolBar = new JToolBar (). setVisible ( true ).add ( loveAction ).add ( panel. setJMenuBar ( menuBar ). //pasang komponen Container contPane = getContentPane (). menuBar. fileMenu.add ( exitAction ). //add action to menu fileMenu.setMnemonic ( 'F' ). fileMenu. //button JButton btnLove = new JButton ( loveAction ). setDefaultCloseOperation ( EXIT_ON_CLOSE ). untuk mempermudah manajemen Event Handler Java GUI (Graphical User Interface) 11 . toolBar. contPane.NORTH ).addSeparator ().add ( exitAction ). toolBar. panel.add ( btnExit ). JButton btnExit = new JButton ( exitAction ).4 – Class SwingAction. //panel untuk memasang button JPanel panel = new JPanel ( new FlowLayout () ).add ( fileMenu ). fileMenu. JMenuBar menuBar = new JMenuBar ().add ( btnLove ). demonstrasi Action dalam aplikasi berbasis Java.add ( loveAction ). 140 ).add ( toolBar.CENTER ). setSize ( 300. BorderLayout. contPane. } Listing 1. panel.

png" ) ) ). } private class LoveAction extends AbstractAction { //konstruktor public LoveAction() { putValue ( Action. } public void actionPerformed( ActionEvent e ) { JOptionPane.NAME.SHORT_DESCRIPTION.4 – Class SwingAction. "Exit Action" ). "Klik di sini untuk keluar" ). deritanya " + "tiada pernah berakhir" ).png" ) ) ).MNEMONIC_KEY.this. putValue ( Action.public static void main( String[] args ) { new SwingActions (). putValue ( Action.SMALL_ICON. new Integer ( 'L' ) ). untuk mempermudah manajemen Event Handler 12 Secangkir Kopi Java .getResource ( "love. "Cinta.MNEMONIC_KEY. putValue ( Action. } Listing 1. putValue ( Action. } } private class ExitAction extends AbstractAction { //konstruktor public ExitAction() { putValue ( Action.SMALL_ICON. //nama putValue ( Action.showMessageDialog ( SwingActions. demonstrasi Action dalam aplikasi berbasis Java.NAME. "Klik di sini untuk melihat ungkapan" + "cinta" ). new ImageIcon ( getClass (). new ImageIcon ( getClass (). //nama putValue ( Action. "Love Action" ).getResource ( "exit. new Integer ( 'X' ) ).SHORT_DESCRIPTION.

Nama Type Deskripsi Digunakan sebagai label dari komponen GUI. Action. Inner Class sangat bermanfaat untuk membuat Action. di sini Aku akan memperkenalkan inner class. Dengan men-subclass-kan pada AbstractAction.SHORT_DESCRIPTION Teks yang digunakan sebagai tool tip text Icon yang ditampilkan pada label komponen Action.exit ( 0 ). Inner Class adalah class biasa yang berada di dalam class lain.SMALL_ICON GUI Kunci yang digunakan pada keyboard. Inisialisasi Action dilakukan dengan memanggil method putValue.4 – Class SwingAction. Action.NAME Jika komponen tsb. Semua instans class utama akan dikenali oleh inner class ini. Berikut ini adalah beberapa hal yang bisa dimasukkan pada method putValue ( int type.public void actionPerformed( ActionEvent e ) { System. Object object ). } } } Listing 1.MNEMONIC_KEY Misalnya ALT+F untuk File. Action. untuk mempermudah manajemen Event Handler Kalau tadi di Web Browser kita menggunakan anonymous class. misalnya. memiliki label tersendiri. demonstrasi Action dalam aplikasi berbasis Java. kita tinggal melakukan inisialisasi dan menulis implementasi actionPerformed saja. Java GUI (Graphical User Interface) 13 . maka label di Action akan diabaikan. Mari kita trace satu per satu: Inner Class LoveAction merupakan subclass dari class AbstractAction.

Dua button ini dipasang dulu dalam sebuah panel sebelum ditempelkan ke kanvas dasar. Jika komponen yang merujuk action ini diaktivasi ( klik ).LONG_DESCRIPTION contohnya untuk help. Action. inilah hasilnya! 14 Secangkir Kopi Java . Misalnya Action. karena jika dipasang langsung pada kanvas dasar. Kemudian actionPerformed pada LoveAction menampilkan pesan pada suatu message box. Class ExitAction tidak jauh berbeda dengan class LoveAction. Memasang menu.ACTION_COMMAND_KEY string yang digunakan di ActionEvent Teks untuk menjelaskan suatu komponen.Kunci untuk shortcut keyboard. Kunci untuk menerima perintah berbentuk Action. pembuatan GUI-nya thok bisa makan waktu yang puanjang. Konstruktor SwingActions akan menginisialisasi semua komponen yang diperlukan dan memasangnya ke kanvas dasar contPane. Ayo DiCompile! Saat yang menyenangkan.ACCELERATOR_KEY CTRL+S untuk menyimpan file. toolBar.. dsb.java Dan kita jalankan dengan perintah: java SwingActions Bismillahi rahmanir rahiim…. apalagi jika susunan komponennya begitu kompleks. Mari kita compile kode yang sudah kita tulis dengan perintah: javac SwingActions. Di sini yang dilakukan adalah keluar sistem. Mungkin ini salah satu kelemahan dari Java. dan terakhir button. Kita akan bahas JOptionPane setelah ini. GUI akan menampilkan message box ini. hasilnya tidak terlalu rapi.

dan dialog pesan. kita bisa memanfaatkan class JOptionPane. menampilkan dialog box Kotak dialog sangat diperlukan ketika menginginkan user input. Syntax umum dari JOptionPane ini adalah Java GUI (Graphical User Interface) 15 . meminta input. Di sini kita bisa menampilkan baik kotak pesan ataupun kotak konfirmasi. dialog input.. atau hanya menampilkan pesan biasa. entah itu konfirmasi. Class JOptionPane. Message Box Untuk menampilkan suatu message box yang indah.iii. bahasaneeee ) semuanya itu dalam class JOptionPane. Swing mengenkapsulasi ( weleh. Ada tiga macam kotak dialog yang disediakan oleh JOptionPane yaitu: dialog konfirmasi.

QUESTION_MESSAGE: Menampilkan icon pertanyaan dengan tanda tanya dengan warna hijau.JOptionPane. Object message.String title. Bentuk ini memberi judul pada window dialog dan memberi jenis dari pesan tersebut.ERROR_MESSAGE: Menampilkan icon error.WARNING_MESSAGE: Menampilkan icon peringatan dengan tanda seru dikelilingi segitiga berwarna kuning. Jika aku menulis kayak gini: JOptionPane. int messageType ). Parent component adalah induk dari kotak dialog ini. Maka hasilnya akan kayak gini: Bentuk kedua adalah JOptionPane. JOptionPane.showMessageDialog( null. JOptionPane. Jika tidak null. "Hai Mata Berbinar!"). Bentuk yang pertama adalah JOptionPane. MessageType tersebut adalah: JOptionPane.showMessageDialog ( Component parent.parameter – ) Java meng-Overload method showMessageDialog hingga tiga bentuk. Object message ). Jenis-jenis tersebut dibedakan dari icon yang ditampilkan. maka kotak dialog akan dilettakkan persis di tengah-tengah window induknya. JOptionPane. Icon-nya mirip-mirip dengan tanda dilarang masuk dan berwarna merah. 16 Secangkir Kopi Java .INFORMATION_MESSAGE: Menampilkan icon informasi dengan huruf (i) seperti gambar di atas.showMessageDialog ( -.showMessageDialog ( Component parent.

- JOptionPane. "Tanya". ada ya.PLAIN_MESSAGE: Menampilkan pesan tanpa icon. untuk mengidentifikasi parent kamu bisa menulis : NamaClass. Untuk menampilkannya. JOptionPane. Jawabannya macammacam. dan batal alias kancil ( cancel ). Bentuk Pertama: JOptionPane. maka hasilnya akan seperti ini: Bentuk ketiga adalah: JOptionPane. Object Java GUI (Graphical User Interface) 17 .showMessageDialog ( Component parent. String title. Object message. int messageType. Jika aku menulis seperti ini: JOptionPane. Icon icon ). Java menyediakan empat model dari kotak konfirmasi ini. ( Component parent. tidak.QUESTION_MESSAGE ).showConfirmDialog message ).this Kotak Konfirmasi ( Confirm Dialog ) Dialog konfirmasi sering digunakan untuk mendapatkan persetujuan user apakah suatu proses dijalankan atau tidak. Bentuk ini akan mengganti icon default dengan icon yang kamu beri sendiri. "Bagaimana hari ini\nApakah” + “indah?".showMessageDialog ( null. Asyik kan? Visual Basic mana bisa begini…… Tips: Jika kamu menampilkan dialog box dalam suatu anonymous class ( misalnya dalam actionPerformed-nya button ).

showConfirmDialog ( Component parentComponent. OptionType itu adalah: JOptionPane. juga mengizinkan menentukan jenis icon yang tampil yang sudah dibahas pada kotak pesan.YES_NO_CANCEL_OPTION: Dia akan menampilkan semua tombol: YES. JOptionPane.showConfirmDialog(Component parentComponent. Akan muncul hasil yang seperti ini: Bentuk kedua adalah seperti ini: JOptionPane. Bentuk ini akan memberi judul pada kotak dialog dan menentukan tombol-tombol / opsi-opsi yang ditampilkan. Bentuk ini selain mengizinkan kamu menentukan tombol apa saja yang tampil. int messageType). Contohnye: kalau aku nulis… 18 Secangkir Kopi Java . String title.YES_NO_OPTION: Hanya akan menampilkan tombol YES dan NO saja. Java meng-overload bentuk ketiga seperti ini: JOptionPane. Jika kamu mau menentukan kotak dialog yang lebih bebas lagi. Jika aku menulis syntax: JOptionPane.Ini adalah bentuk yang paling sederhana dari kotak konfirmasi. String title. int optionType. Object message. dan CANCEL. NO.showConfirmDialog(null. Object message. int optionType). "Jadi nggak?").

JOptionPane. int messageType.showConfirmDialog ( null.YES_NO_OPTION.. taruh di sini } Java GUI (Graphical User Interface) 19 . "Document change. Object message. Ini dia: JOptionPane. “Akankah dia membuat luka kecil lagi?” ).showConfirmDialog ( null. JOptionPane.showConfirmDialog(Component parentComponent. Bagaimana cara mendeteksi bahwa user memencet tombol YES. Jadinya: Masih kurang puas? Weleh. "Saving Option". Do you want to save changes?".WARNING_MESSAGE )..weleh… ada bentuk terakhir dari kotak konfirmasi ini yang paling lengkap. int optionType. Wis selamat berkreasi… Ketika aku mengenal kotak konfirmasi.JOptionPane. atau NO? Oh.YES_OPTION ) { //. di benakku timbul pertanyaan. Kalau masih kurang puas. Icon icon). jika yes ngapain. buat kotak konfirmasi sendiri dengan men-subclass-kan pada JDialog. jawabnya mudah saja. CANCEL. String title.showConfirmDialog akan mereturn sebuah nilai integer yang bisa kamu bisa masukkan ke dalam suatu blok if seperti ini: int result = JOptionPane. JOptionPane. if ( result == JOptionPane. Bentuk ini mengizinkan kamu untuk mengganti icon dengan yang sesuai seleramu.

aku selalu memakai fungsi getche() dalam blok do-while untuk mendapatkan masukan dari user. Kotak input yang sangat dinamis dan fleksibel.NO_OPTION ) { //. Kurasa. taruh di sini } else { // yang ini mah pasti cancel } Listing 1. jika no ngapain..showInputDialog ( Component parentComponent. Aku ingat. Java memiliki enam bentuk kotak input ini.5 – Bagaimana mendeteksi user menekan tombol tertentu pada kotak dialog konfirmasi Yes No Cancel? Kotak Input / Input Dialog Kotak input penting untuk mendapatkan masukan dari user.showInputDialog(null. Akan muncul dialog seperti ini: Bentuk Kedua: 20 Secangkir Kopi Java . "Berapa umurmu?"). Bentuk Pertama: JOptionPane. Object message ). hanya Swing yang memiliki kotak input serame ini. Bentuk yang paling sederhana.else if ( result == JOptionPane. Jika aku menulis JOptionPane. ketika Aku memakai bahasa C semester I dan II kemarin.

String title. Object initialSelectionValue). Ketiga bentuk terdahulu akan mereturn tipe data String. int messageType). null.QUESTION_MESSAGE. Bentuk ini akan memberi nilai default pada teks box pada dialog input. null ). Bentuk Ketiga: JOptionPane. String title. sedangkan bentuk ini akan mereturn Object. Bentuk ini sama dengan kotak pesan dengan memberikan jenis icon. Bentuk yang paling lengkap dari kotak dialog input ini. maka yang digunakan bisa JComboBox atau JList. "Berapa umurmu?". Object initialSelectionValue).showInputDialog(Component parentComponent. "13".showInputDialog ( null. Bentuk Keempat: JOptionPane. Jika selectionValues null. Object message.showInputDialog(Component parentComponent. Maka hasil yang muncul cukup aneh: Java GUI (Graphical User Interface) 21 . umur.showInputDialog(Component parentComponent. "Umur". Jika tidak null. Object message. "14" }. maka komponen untuk memasukkan inputan adalah JTextField. hanya bedanya di sini terdapat teks box tempat user memasukkan inputan. int messageType. Jika Aku nulis kayak gini: String[] umur = { "12". Icon icon. JOptionPane.JOptionPane. JOptionPane. Object[] selectionValues. Object message.

Kamu harus melakukan explicit casting untuk mendapatkan tipe data yang sebenarnya.showInputDialog(Object message).Perhatikan bahwa yang muncul bukanlah JTextField. Mereka merupakan bentuk yang paling sederhana dari kotak input ini. Bentuk Keenam: JOptionPane. 22 Secangkir Kopi Java .showInputDialog(Object message. melainkan sebuah JComboBox! Dan return value dari bentuk ini adalah Object. Kedua bentuk di atas tidak memiliki parent component atau null. Bentuk Kelima: JOptionPane. Object initialSelectionValue).

view controller januari 2004 .model .

.

MVC diperkenalkan oleh Smalltalk-80. Aku belum pernah menulis JList. maka kuputuskan untuk memasukkannya ke dalam diary-ku ini.. JList Sejujurnya. dan Print Layout. dan empat View. Controller bisa berwujud keyboard ataupun mouse. Misalnya.. please welcome: Jeeeeeeee Liiiiiiist!!!!!! 25 Model View Controller . aduh… kapan kamu akan percaya Aku? Wis. Ketika data model dimodifikasi lewat controller. Satu data model bisa memiliki lebih dari satu view. JList relatif paling mudah dimengerti daripada JTable dan JTree.he. sedangkan model adalah data yang sesungguhnya yang berada di balik View. Tapi karena JList juga termasuk MVC. Model-View memudahkan kita untuk mengatur pengolahan data. Controller adalah bagian yang mengubah-ubah data model. he. yaitu Normal. keempat View langsung menyesuaikan diri dengan data model yang baru.. View adalah bagaimana data tersebut ditampilkan di layar atau di printer..he. Perl. Itung-itung juga belajar. Bagaimana bentuk bahasa itu Aku juga nggak tahu. sama nggak tahunya Aku dengan bahasa Lisp. Nggak percaya? Aduh. Kalau Aku boleh menggambar diagram. satu document MS-Word yang sedang kutulis ini memiliki satu model. langsung aja kuperkenalkan… Ladies and gentlemen. Web. yaitu document ini sendiri. Outline. arsitektur MVC itu adalah seperti ini: CONTROLLER MODEL CONTROLLER VIEW VIEW i. MVC yang pernah kupelajari hanyalah JTree dan JTable.Kata buku. dan bahkan Pascal aku nggak tahu! Model View Controller membedakan suatu data menjadi bagian view dan bagian model.

Multiple-Interval Selection.1 – Class ListDemo.util.*. kamu harus memasukkannya ke dalam JScrollPane. private JComboBox combo1. public class ListDemo extends JFrame { private JList list1. menampilkan bagaimana sebuah List dibangun dengan JList. JList ( Vector data ) akan membentuk JList dengan data yang ada pada Vector. import java. single-interval selection. import java. private JList list2. Untuk mendapatkannya. komponen swing yang berbasis Model-View 26 Secangkir Kopi Java .util. private JComboBox combo2.*. kita hanya boleh memilih satu dari sekian banyak daftar di List.event. import javax.awt.event. Kita akan bahas ini lebih mendetail nanti. JList ( ListModel listModel ) akan membentuk JList dengan sebuah ListModel.swing.swing. dan multiple-interval selection. kita boleh memilih lebih dari satu. Single-Interval Selection. JList tidak mendukung scrolling secara langsung.*. import java. import javax. JList ( Object[] data ) akan membentuk sebuah JList yang berisi data pada array Object[ ] data.*. JList mendukung tiga macam cara seleksi yaitu: seleksi tunggal ( single selection ). ListModel adalah implementasi dari MVC sebenar-benarnya. Vector adalah array dinamis pada Java yang terdapat dalam package java. Seleksi tunggal.awt. kita boleh memilih memilih lebih dari satu dan boleh tidak berurutan alias mblejog-mblejog ( tulungagung buanget… ). Listing 2. tetapi harus berurutan.*.Kamu bisa membangun JList melalui empat konstruktornya: JList() akan membentuk sebuah JList yang kosong ( buat apa? ).

add ( "Mika Hakkinen" ). list1 = new JList ( listData1 ).SINGLE_SELECTION ). "Jambu".private JLabel statusBar = new JLabel ( "Status Bar" ). listData2. "Manggis".setSelectionMode ( ListSelectionModel.add ( "David Coulthard" ). listData2. "Kelapa". listData2.add ( "Ayrton Senna" ). list1.add ( "Rubens Barichello" ). menampilkan bagaimana sebuah List dibangun dengan JList.add ( "Michael Schumacher" ). "Mangga".1 – Class ListDemo. "Pisang".add ( "Jacques Villeneuve" ). listData2. listData2. //list dengan data vector Vector listData2 = new Vector ().setSelectionMode ( ListSelectionModel. public ListDemo() { super ( "List Demo" ). list2 = new JList ( listData2 ). setEventHandler (). komponen swing yang berbasis Model-View Model View Controller 27 . } private void createGUI() { //list dengan data array String[] listData1 = { "Apel". listData2. listData2. list2. "Meloon" }. Listing 2. createGUI (). "Pepaya". "Jeruk".add ( "Juan Pablo Montoya" ). listData2.add ( "Kimi Raikonnen" ). listData2. //combo box data String[] selection = { "SINGLE_SELECTION". listData2.SINGLE_SELECTION ).add ( "Ralf Schumacher" ). "Semangka".add ( "Alain Prost" ).

Container contPane = getContentPane (). 250 ). 160 ) ). scrPane1. BorderLayout. "MULTIPLE_INTERVAL_SELECTION" }. BorderLayout. //pasang ke kanvas JScrollPane scrPane1 = new JScrollPane ( list1 ). menampilkan bagaimana sebuah List dibangun dengan JList.add ( panelKanan ).add ( listPanel. 2 ) ).add ( scrPane1. komponen swing yang berbasis Model-View 28 Secangkir Kopi Java . panelKiri. contPane. 160 ) ). setSize ( 450.CENTER ).CENTER ).add ( panelKiri ).SOUTH ). JPanel panelKanan = new JPanel (). BorderLayout.NORTH ). listPanel. panelKiri.setPreferredSize ( new Dimension ( 220. BorderLayout. combo2 = new JComboBox ( selection ). scrPane2. BorderLayout. JPanel listPanel = new JPanel ( new GridLayout ( 1. } private void setEventHandler() { Listing 2.add ( combo2."SINGLE_INTERVAL_SELECTION".add ( statusBar.add ( combo1. panelKanan. JScrollPane scrPane2 = new JScrollPane ( list2 ).NORTH ). JPanel panelKiri = new JPanel ().CENTER ). panelKanan. setVisible ( true ). contPane. setDefaultCloseOperation ( EXIT_ON_CLOSE ).add ( scrPane2.setPreferredSize ( new Dimension ( 220. combo1 = new JComboBox ( selection ).1 – Class ListDemo. BorderLayout. listPanel.

} else { list1.setSelectionMode ( ListSelectionModel.equals ( "SINGLE_INTERVAL_SELECTION" ) ) { list1. Listing 2.SINGLE_SELECTION ).//combo box kiri combo1.setSelectionMode ( ListSelectionModel.setSelectionMode ( ListSelectionModel. //combo box kanan combo2. SINGLE_INTERVAL_SELECTION ).setSelectionMode ( ListSelectionModel. } else if ( text.addActionListener ( new ActionListener () { public void actionPerformed( ActionEvent e ) { String text = ( String ) combo1.addActionListener ( new ActionListener () { public void actionPerformed( ActionEvent e ) { String text = ( String ) combo2. SINGLE_INTERVAL_SELECTION ).1 – Class ListDemo.setSelectionMode ( ListSelectionModel. MULTIPLE_INTERVAL_SELECTION ).SINGLE_SELECTION ). if ( text. if ( text.getSelectedItem ().getSelectedItem ().equals ( "SINGLE_SELECTION" ) ) { list1.equals ( "SINGLE_INTERVAL_SELECTION" ) ) { list2. } else if ( text. komponen swing yang berbasis Model-View Model View Controller 29 . menampilkan bagaimana sebuah List dibangun dengan JList. } } } ).equals ( "SINGLE_SELECTION" ) ) { list2.

list2. for ( int i = 0. String display = "". i++ ) { display += ( String ) selectedItems[i] + " ". komponen swing yang berbasis Model-View 30 Secangkir Kopi Java .length.1 – Class ListDemo. i < indices. getSelectedValues (). Object[] selectedItems = list1.length. } } ). } statusBar. } } } ).setText ( display ). i++ ) { display += ( String ) selectedItems[i] + " ". i < indices. } Listing 2.addListSelectionListener ( new ListSelectionListener () { public void valueChanged( ListSelectionEvent e ) { int[] indices = list1.} else { list2. MULTIPLE_INTERVAL_SELECTION ). menampilkan bagaimana sebuah List dibangun dengan JList.getSelectedIndices ().getSelectedIndices (). String display = "". //list listener list1. for ( int i = 0.setSelectionMode ( ListSelectionModel. Object[] selectedItems = list2. getSelectedValues ().addListSelectionListener ( new ListSelectionListener () { public void valueChanged( ListSelectionEvent e ) { int[] indices = list2.

Apa yang diklik akan ditampilkan di status bar. Kita dapatkan kumpulan index dari daftar list yang terpilih dengan memanggil method getSelectedIndices() dan Model View Controller 31 . JComboBox juga memiliki model. sehingga isinya ditambahkan dengan memanggil method add. } } ). } } Listing 2. Di sini kita menambahkan “telinga” itu dengan cara addListSelectionListener.statusBar. komponen swing yang berbasis Model-View Di sini ada dua JList yang dibentuk dengan cara yang berbeda. isi vector masih kosong. JComboBox digunakan untuk mengatur cara JList memilih daftar. Ketika suatu anggota JList dipilih. setelah semua komponen dipasang di dalam container. dan di sini yang digunakan adalah array String. Satu dengan data model array dan satunya lagi memakai Vector. } //launcher public static void main( String[] args ) { new ListDemo (). program akan memanggil method valueChanged ( ListSelectionModel e ) yang berada dalam interface ListSelectionListener. menampilkan bagaimana sebuah List dibangun dengan JList. Kemudian.setText ( display ). Di sini Aku memakai tipe data String.1 – Class ListDemo. Vector diinisialisasi dengan kata kunci new. Pada saat diinisialisasi. Status bar adalah JLabel biasa yang kita tempatkan di container paling bawah ( SOUTH ) dalam layout BorderLayout. JList dipersenjatai agar bisa mendengarkan event. namun sebenarnya JList bisa dimasuki tipe data Object.

Jika lancar. kemudian jalankan dengan java.kita simpan dalam array integer. dilanjutin nanti pembahasannya. seperti misalnya: String[] items = ( String[] ) list1.getSelectedItems(). Gambar 2.1 – Tampilan dari JList kita. Duh…. Pertama kita dapatkan nilai yang terpilih pada JComboBox kemudian kita sesuaikan JList dengan memanggil method setSelectionModel(). JVM akan menolaknya. Compiler akan meluluskan kode di atas. Jangan melakukan Explicit Casting di sini. window yang akan keluar kayak gambar di bawah. Kita juga dapatkan item yang terpilih dengan method getSelectedItems(). patah hati dunk.. 32 Secangkir Kopi Java . Yang terakhir adalah menghubungkan JComboBox dengan JList.. Tiga tipe selecting tersebut ada di interface ListSelectionModel. namun ketika run time. Oce kan? Wis ya. Method ini mereturn suatu array Object. Setelah dapat keduanya. kita tambahkan satu per satu ke String dan kita tampilkan di JLabel dengan method setText ( String text ). Oce! Compile kode di atas dengan javac. tak liat AFI 3 dulu…….

*. listFile = directory. kita hanya perlu berpikir bagaimana isi dari method-method yang ada dalam interface ListModel.directory = directory. Di dalam interface ini terdapat method-method yang masih belum diimplementasikan yang bisa kita pakai secara sesuka hati. untuk mendapatkan model dari JList supaya lebih customizable ( hmmm. private String[] listFile.io. Sekarang kita pingin donk mendandani JList kita supaya lebih menarik lagi… Konstruktor ketiga dari JList adalah JList ( ListModel model ). public class MyListModel implements ListModel { private File directory. ListModel adalah interface yang digunakan sebagai model dari JList. artine opo ). //konstruktor public MyListModel( String dir ) { File directory = new File ( dir ).. import javax.swing.*. Sudah kita bahas habis JList dengan default konstruktor dan default modelnya serta tampilan defaultnya.*.swing. dengan mendaftar sebuah file dari direktori.list().2 – Class MyListModel yang mengimplementasikan interface ListModel. this. import java. } Listing 2. import javax.Advanced JList Well… sekarang akan kuperkenalkan JList tingkat lanjut.event. Kita tak perlu bingung bagaimana JList akan membuat interface ListModel berguna baginya. Model View Controller 33 . Listing kode di bawah ini adalah sebuah implementasi ListModel yang akan kita gunakan dalam JList nanti.

Hasil dari method list() adalah sebuah array String. Nah! Sekarang sudah kita dapatkan datanya.length. File directory akan mendaftar siapa saja anak-anaknya dengan method list(). cek dulu apakah directory benarbenar sebuah folder dengan memanggil isDirectory(). Dua method terakhir tidak kita gunakan di 34 Secangkir Kopi Java . Jika kamu ingin menambahkan error checking di sini. } } Listing 2. maka kita bisa memberi informasi panjang array ( length ) sebagai return value getSize()./////////implementasi interface list model///////////// public int getSize() { return listFile.2 – Class MyListModel yang mengimplementasikan interface ListModel. Method getElementAt ( int i ) berusaha untuk mendapatkan sesuatu yang ada di index ke-i. } public Object getElementAt ( int i ) { return listFile[i]. artine opo ). Konstruktor MyListModel akan melakukan inisialisasi seperti membuat sebuah File dari String dir. Di sini kita berikan isi dari array index kei sebagai return value-nya... } //implementasi ini tidak kita gunakan public void addListDataListener ( ListDataListener l ) { //. } public void removeListDataListener ( ListDataListener l ) { //. Karena data kita adalah array. untuk mendapatkan model dari JList supaya lebih customizable ( hmmm. Method getSize() adalah method untuk mengetahui seberapa panjang daftar list kita nanti..

Object value. Segala kemampuan JLabel bisa ditampilkan di dalam List. boolean isSelected. Model View Controller 35 . karena kita tidak memerlukan telinga ketika pada data model terjadi perubahan.3 – Class MyListCellRenderer yang mengimplementasikan ListCellRenderer else { kandung dari JLabel.swing.. int index.*. setForeground ( Color. Bagaimana mendandaninya supaya ada iconnya? Kita bisa “menempelkan” sebuah JLabel – atau semua anak dari JComponent -.awt.white ). setIcon ( new ImageIcon ( getClass(). untuk mendandani JList supaya berwajah dan merupakan anak JLabel. public class MyListCellRenderer extends JLabel implements ListCellRenderer { //konstruktor public MyListCellRenderer() { setOpaque ( true ).toString() ). } //method aseli dari interface ListCellRenderer public Component getListCellRendererComponent ( JList list. if ( isSelected ) { setBackground ( new Color ( 36. } Listing 2. 9 ) ). Listing kode berikut ini akan menggunakan JList sebagai renderer dan MyListModel sebagai data modelnya. dicuekin aja! JList Renderer Kita sudah menguasai habis soal ListModel.4 API.getResource( "folder. import java.sebagai daftar dari JList.sini. boolean cellHasFocus ) { setText ( value.*. Asyik kan? Aku menemukan cara ini di JDK 1. Kalau terjadi perubahan ya. import javax. 72.png" ) ) ).

3 ) untuk ditampilkan menjadi JList dengan model dan make-up yang baru 36 Secangkir Kopi Java . public class ListDemo2 extends JFrame { private JList list. import javax. untuk mendandani JList supaya berwajah JLabel.2 dan 2. Class MyListCellRenderer adalah sub-class dari JLabel yang digunakan sebagai komponen perender dari JList nanti. yang akan mereturn suatu Component yang digunakan JList sebagai perender dirinya. setForeground ( Color. } } Listing 2.setBackground ( Color. Class ini juga mengimplementasikan interface ListCellRenderer. import java. createGUI(). Listing 2.*.0" ). dan menaruh icon untuk mempercantik JLabel. Inti dari interface ListCellRenderer adalah method getListCellRendererComponent.4 – Class ListDemo2 mengumpulkan dua class terdahulu ( Listing 2.awt.*. } return this.swing. agar bisa digunakan sebagai renderer dari JList. } private void createGUI() { MyListModel listModel = new MyListModel ( "F:/My Documents" ).3 – Class MyListCellRenderer yang mengimplementasikan ListCellRenderer dan merupakan anak kandung dari JLabel. public ListDemo2() { super ( "JList Demo ver 2.black ).green ). Yang kita lakukan di dalam method ini adalah melakukan pendadanan JLabel seperti menset warna background dan foreground baik saat dipilih maupun tidak.

2 – Customized JList.list = new JList ( listModel ). Tak ada yang istimewa.4 – Class ListDemo2 mengumpulkan dua class terdahulu ( Listing 2. pack().2 dan 2. } public static void main ( String[] args ) { new ListDemo2(). setVisible ( true ).setCellRenderer( new MyListCellRenderer() ). hanya memasang JList dalam container dan mendadani JList kita agar bisa menampilkan folder My Documents dengan make-up JLabel.CENTER ). } } Listing 2. getContentPane(). BorderLayout.add( new JScrollPane ( list ).3 ) untuk ditampilkan menjadi JList dengan model dan make-up yang baru Listing di atas adalah kode launcher dari dua class terdahulu. list. kirakira kayak gini deh… Gambar 2. setDefaultCloseOperation ( EXIT_ON_CLOSE ). dengan model file folder F:/My Documents dan Cell Renderer JLabel Model View Controller 37 . Kayak apa sih Lih hasil jadinya? Mmm….

dan cell dari tabel. ColumnModel. atau Microsoft Excel dan melihat tampilan worksheet-nya.. Tetapi kamu bisa memasukkannya ke dalam sebuah JScrollPane untuk mendapatkan dukungan itu. Oce. TableModel digunakan untuk menyimpan dan memproses data. Jika kamu menginginkan tabel-mu read only. Nah. nggak usah muna. ☺ Kamu tentu sudah pernah membuka Microsoft Access. JTable tidak secara langsung mendukung scrolling.he. kita emang pengguna Microsoft Windows kok. Tidak main-main. dan ListSelectionModel. 38 Secangkir Kopi Java . cell editor dari JTable adalah JTextField. JTable memiliki sangat banyak fitur untuk kebutuhan editing dan rendering.JTable. Mereka adalah TableModel. Kamu bisa melihatnya sendiri di dokumentasi javadoc untuk javax. ColumnModel digunakan untuk manajemen kolom dari tabel. JTable juga merupakan sebuah Model-View Controller. JTable Apakah kamu seorang pecinta Windows? Agen Kapitalis Microsoft? Kalau jawabannya ‘ya’.. dan ListSelectionModel digunakan untuk memilih baris.. JTable memiliki tiga model yang berbeda. namun kamu bisa memaksanya menjadi JComboBox ataupun komponen lain. JTable akan menyembunyikan headernya jika kamu tidak memasukkannya ke dalam JScrollPane. Seperti halnya JList.he. Secara default. Tapi menurutku. Aku tidak membahasnya satu per satu karena terlalu bertele-tele. sekarang kita bicara lebih teknis lagi soal JTable. JTable memiliki tujuh konstruktor. he.ii. kamu harus mengoverride-nya lewat TableModel. kolom. JTable memiliki cell editor dan cell renderer. itulah yang namanya komponen Table. Secara default.swing. Swing memiliki komponen yang menyajikan data dalam baris dan kolom yang dinamakan JTable. JTable adalah fulleditable. berarti sama dengan aku donk.

Gunanya untuk menunjukkan apakah kolom-kolom dibuat dari table model. Object[] columnNames ). editingRow: Baris dari cell yang sedang diedit. Nilai defaultnya adalah true. Mereka adalah: autoCreateColumnsFromModel: Bertipe boolean. Berikut ini adalah kemungkinan bagaimana kolom JTable dimanipulasi: JTable. Oke. Masih segudang lagi properti dari JTable yang bisa kita ubah-ubah sesuai kebutuhan kita.AUTO_RESIZE_LAST_COLUMN JTable. Semuanya bisa dilihat di dokumentasi dari JTable.AUTO_RESIZE_ALL_COLUMNS cellSelectionEnabled: Bertipe boolean. autoResizingMode: Kamu bisa me-resize lebar kolom semaumu selama programmer tidak membatasi lebar maksimal dari kolom setiap saat.konstruktor di bawah ini cukup representatif untuk menjelaskan soal JTable.AUTO_RESIZE_OFF JTable. Menunjukkan apakah boleh kita memilih suatu cell secara individual. public JTable ( Object[][] rowData.AUTO_RESIZE_NEXT_COLUMN JTable. Sebelum kita menginjak ke bagian coding. kamu tidak bisa seenak udel mengubahnya. Yuk… Model View Controller 39 . mari kita test beberapa properti dari JTable dalam sebuah tampilan sederhana. aku perlu memperkenalkan properti yang dimiliki oleh JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable. Tetapi untuk baris. columnSelectionAllowed: Nilai boolean yang menunjukkan apakah kolom JTable boleh dipilih atau tidak. editingColumn: Kolom dari cell yang sedang diedit.

setEventHandler().addActionListener( new ActionListener() { public void actionPerformed ( ActionEvent e ) { int rowHeight = new Integer ( txtRowHeight. private JTextField txtRowHeight = new JTextField ( 5 ). ( Sederhana?!?!?! ) 40 Secangkir Kopi Java . } private void setEventHandler() { //row height txtRowHeight. } }).awt. trim() ). table. //konstruktor public TableDemo() { super ( "Table Properties Demo" ).5 – Class TableDemo.*.swing.*. createGUI(). import java. class yang menunjukkan beberapa penggunaan properti JTable dan dibangun dengan konstruktor yang cukup sederhana.addActionListener( new ActionListener() { public void actionPerformed ( ActionEvent e ) { Listing 2.awt. private JCheckBox chkShowGrid = new JCheckBox ( "Show Grid" ). private JTextField txtRowMargin = new JTextField ( 5 ).getText().event.setRowHeight( rowHeight ).swing.*. import java.intValue(). public class TableDemo extends JFrame { //instance private JTable table. //row margin txtRowMargin.package galih. import javax.

"??".setShowGrid( chkShowGrid.int rowMargin = new Integer ( txtRowMargin. "Prentice Hall Inc" }.NET Web Developer's Guide". "Prentice Hall Inc" }.5 – Class TableDemo.addActionListener( new ActionListener() { public void actionPerformed ( ActionEvent e ) { table. } }). "HM. Listing 2. } //membangun user interface private void createGUI() { //data tabel String[][] tableData = { { "Advanced Java 2 How To Program". { "Macromedia Flash MX Action Script for Designer". "Patrick Naughton". table. "Wiley Publishing Inc" } }.getText(). "SynGress Wallet Inc" }. "Adrian Turtschi".setRowMargin( rowMargin ). trim() ). Deitel". { "OpenGL Programming Guide". "Penerbit" }. "Penulis". "Doug Sahlin". { "Java Handbook". //table header String[] tableHeader = { "Judul Buku". //show grid chkShowGrid. { "MySQL/PHP Applications". class yang menunjukkan beberapa penggunaan properti JTable dan dibangun dengan konstruktor yang cukup sederhana. "M&T Books" }. "Addison-Wesley Publishing Company" }. "Jay Greenspan".isSelected() ). } }). ( Sederhana?!?!?! ) Model View Controller 41 . { "C# .intValue().

200 ). 1 ) ). JPanel panel3 = new JPanel ( new GridLayout ( 1 .valueOf( table. txtRowMargin.add( panel3. setVisible ( true ).setText( String.add( new JLabel ( "Row Margin" ) ). JPanel panel2 = new JPanel ( new FlowLayout() ). ( Sederhana?!?!?! ) 42 Secangkir Kopi Java .5 – Class TableDemo. cp. } } Listing 2.getRowHeight() ) ). panel2. BorderLayout.add( new JLabel ( "Show Grid" ) ). panel2. setDefaultCloseOperation ( EXIT_ON_CLOSE ). setSize ( 450.setText( String. Container cp = getContentPane().add( chkShowGrid ).add( new JLabel ( "Row Height" ) ).//inisialisasi tabel table = new JTable ( tableData.add( txtRowHeight ). class yang menunjukkan beberapa penggunaan properti JTable dan dibangun dengan konstruktor yang cukup sederhana. panel2. BorderLayout. //init text box txtRowHeight. cp.valueOf( table. //init check box chkShowGrid. panel2. panel3.add( txtRowMargin ). } //launcher public static void main ( String[] args ) { new TableDemo().NORTH ). tableHeader ).add( new JScrollPane ( table ).setSelected( true ).getRowMargin() ) ).CENTER ).add( panel2 ). panel2. panel2.

hasilnya seperti ini… Gambar 2. Oke. Gimana Lih hasilnya? Di kompie-ku.Kurasa. kita perlu mendemonstrasikan bahwa ternyata garis pembatas pada JTable bisa dihilangkan dengan memasang sebuah check box di situ. Kemudian kedua string itu kita masukkan sebagai parameter dari konstruktor JTable. kulayani permintaanmu. Gimana…? ☺ Advanced JTable Dasar-dasar JTable telah kita kuasai.3 – Hasil dari koding di atas jika dijalankan pakek Java Virtual Machine. Terakhir. Kita mempersiapkan dua array String. Sekarang tentunya kamu ingin tantangan yang lebih berat bukan? ( bukaaan… ). Yang pertama adalah array dua dimensi untuk data tabel dan yang kedua adalah array satu dimensi untuk kepala kolomnya. Model View Controller 43 . Di sini kita juga mengubah-ubah lebar baris dan jarak dari masing-masing baris lewat text box txtRowHeight dan txtRowMargin. Event yang kita masukkan pada addActionListener akan dikerjakan ketika kita menekan tombol Enter saat salah satu text box itu terfokus. Aku akan membahas soal bagaimana mendandani JTable seperti halnya kita mendadani JList. hanya sedikit yang perlu dijelaskan di sini.

Table Column Model Table Column Model digunakan untuk mengatur kolom dari JTable. public int getColumnCount().Sudah kukatakan sejak awal bahwa JTable memiliki tiga model yang berbeda. Data yang akan dimodifikasi. public Object getValueAt ( int row. yang nantinya dimanfaatkan oleh JTable sebagai model datanya. Kita akan membahasnya satu per satu. implementasi dari TableModel tentunya class cukup yang AbstractTableModel adalah mengimplementasikan hampir seluruh method yang ada pada interface TableModel. Beberapa method dari class DefaultColumnModel adalah: Untuk memanipulasi kolom: public void addColumn(TableColumn tableColumn) public void removeTableColumn(TableColumn tableColumn) 44 Secangkir Kopi Java . Setiap model harus mengimplementasikan interface TableColumnModel. Kita cukup menulis implementasi untuk method: public int getRowCount(). Kita bisa menggunakan class DefaultTableModel jika data yang kita sajikan tidak terlalu rumit ( jika data adalah hasil query dari database. Di dalam vector tersebut masing-masing terdapat sebuah array yang elemennya merepresentasikan kolom dari baris tertentu. int col ). Semua table model harus mengimplementasikan interface TableModel. Namun kurasa class default-nya sudah cukup untuk memanipulasi kolom dari JTable. Table Model Table Model digunakan untuk memanipulasi data yang akan disajikan di JTable. sebaiknya jangan menggunakan DefaultTableModel ). ataupun menambah data baru harus lewat pintu ini. Menulis membosankan. Class DefaultTableModel adalah subclass dari class AbstractTableModel yang menggunakan Vector sebagai penyimpan datanya. dihapus.

int toIndex) public int getColumnMargin() public void setColumnMargin(int newMargin) public TableColumn getColumn(int columnIndex) public int getColumnCount() public int getColumnIndex(Object columnIdentifier) public Enumeration getColumns() public int getTotalColumnWidth() Untuk memilih kolom: public boolean getColumnSelectionAllowed() public void setColumnSelectionAllowed(boolean flag) public int getSelectedColumnCount() public int getSelectedColumns() public ListSelectionModel getSelectionModel() public void setSelectionModel(ListSelectionModel newModel) Class TableColumn Class TableColumn berhubungan dengan semua kolom pada JTable. public int getWidth() public void setWidth(int width) public int getMaxWidth() public void setMaxWidth(int maxWidth) public int getMinWidth() public void setMinWidth(int minWidth) public int getPreferredWidth() public void setPreferredWidth(int minWidth) Model View Controller 45 . Class ini digunakan untuk memanipulasi suatu kolom tertentu secara individual pada JTable.public void moveColumn(int fromIndex. Class ini tidak dapat dibuat secara langsung ( instantiated ). dan header renderer. menentukan cell renderer dan cell editor. tetapi kita bisa mendapatkan objek ini dari method getColumn ( int index ) pada TableColumnModel atau method getColumn ( Object identifier ) pada JTable. Beberapa method di bawah ini adalah milik class TableColumn untuk mengatur panjang kolom.

Listing 2. Okay? Let’s go! package galih. import java. private JButton btnRemoveRow = new JButton ( "Remove Row" ).swing. kita dapat menambah dan menghapus baik baris ataupun kolom. Siapkan dirimu untuk membaca kode gila! Tapi itu akan percum tak bergun jika kamu tidak mencobanya sendiri.0" ).*. private JButton btnRemoveCol = new JButton ( "Remove Column" ).*. 46 Secangkir Kopi Java . //konstruktor public TableDemo2() { super ( "Table Demo ver 2.swing.6 – Dengan TableModel. Di sini diperkenalkan dua model.awt.*. yaitu TableModel dan ColumnModel. import javax.Urusan Renderer dan Editor: public TableCellEditor getCellEditor() public void setCellEditor(TableCellEditor anEditor) public TableCellRenderer getCellRenderer() public void setCellRenderer(TableCellRenderer aRenderer) public TableCellRenderer getHeaderRenderer() public void setHeaderRenderer(TableCellRenderer aRenderer) Sekarang kita akan mencoba memanfaatkan class DefaultTableModel untuk menambah dan menghapus data pada JTable. private DefaultTableModel tableModel. import java. import javax. private JButton btnAddRow = new JButton ( "Add Row" ).event. public class TableDemo2 extends JFrame { //instans private JTable table.awt.table. private JButton btnAddCol = new JButton ( "Add Column" ).*.swing.

tableModel. int selectedCol = table.getColumn( selectedCol ).getSelectedColumn(). } }).getColumnModel().getSelectedRow().createGUI(). //hapus baris btnRemoveRow. yaitu TableModel dan ColumnModel. //nambah kolom kosong btnAddCol. "" }. Model View Controller 47 . //hapus kolom btnRemoveCol. setEventHandler(). Di sini diperkenalkan dua model.addActionListener( new ActionListener() { public void actionPerformed ( ActionEvent e ) { DefaultTableColumnModel columnModel = ( DefaultTableColumnModel ) table. } }).6 – Dengan TableModel.removeRow( selectedRow ).addRow( newRow ).addColumn( "Kolom Baru" ). } }). "". kita dapat menambah dan menghapus baik baris ataupun kolom. tableModel. Listing 2. TableColumn tableColumn = columnModel.addActionListener( new ActionListener() { public void actionPerformed ( ActionEvent e ) { int selectedRow = table.addActionListener( new ActionListener() { public void actionPerformed ( ActionEvent e ) { tableModel. } private void setEventHandler() { //nambah baris kosong btnAddRow.addActionListener( new ActionListener() { public void actionPerformed ( ActionEvent e ) { String[] newRow = { "".

"Penulis".6 – Dengan TableModel. "Doug Sahlin". Di sini diperkenalkan dua model. "M&T Books" }. btnAddCol. "O'Reilly Publishing" } }. { "Java Handbook". Listing 2.setMnemonic( 'C' ). kita dapat menambah dan menghapus baik baris ataupun kolom. { "Macromedia Flash MX Action Script for Designer". { "MySQL/PHP Applications". "Penerbit" }. { "J2ME in A Nutshell". "Addison-Wesley Publishing Company" }. //table header String[] tableHeader = { "Judul Buku". { "OpenGL Programming Guide". } private void createGUI() { //data tabel String[][] tableData = { { "Advanced Java 2 How To Program". btnRemoveRow. "Prentice Hall Inc" }.NET Web Developer's Guide".setMnemonic( 'o' ). "Adrian Turtschi".columnModel. } }). "Waah Lupa Aku".setMnemonic( 'R' ).removeColumn( tableColumn ). yaitu TableModel dan ColumnModel. "SynGress Wallet Inc" }. 48 Secangkir Kopi Java . Deitel". "Wiley Publishing Inc" }. "??". //init table model tableModel = new DefaultTableModel ( tableData. "Jay Greenspan". tableHeader ). "Patrick Naughton". //pasang pada container btnAddRow. table = new JTable ( tableModel ). "Prentice Hall Inc" }. { "C# . "HM.

btnRemoveCol.setMnemonic( 'v' );

JPanel panel1 = new JPanel ( new GridLayout ( 2, 2 ) ); panel1.add( btnAddRow ); panel1.add( btnAddCol ); panel1.add( btnRemoveRow ); panel1.add( btnRemoveCol );

Container cp = getContentPane(); cp.add( panel1, BorderLayout.NORTH ); cp.add( new JScrollPane ( table ), BorderLayout.CENTER );

setDefaultCloseOperation ( EXIT_ON_CLOSE ); setSize ( 400, 300 ); setVisible ( true ); }

//launcher public static void main ( String[] args ) { new TableDemo2(); } }
Listing 2.6 – Dengan TableModel, kita dapat menambah dan menghapus baik baris ataupun kolom. Di sini diperkenalkan dua model, yaitu TableModel dan ColumnModel.

Okay, cukup sederhana. Inisialisasi tabel hampir sama dengan listing 2.5, yaitu dengan menggunakan dua array String. Hanya saja di sini kita menggunakan class DefaultTableModel sebagai table modelnya. Class DefaultTableModel adalah class yang mengimplementasikan interface TableModel. Class ini sangat powerfull untuk melakukan manipulasi data dari tabel. Sedikit dari blok kode pemasangan pada container. Method
setMnemonic ( char x ) untuk menanam fungsi keyboard ALT + (char

x) pada button. Jika kamu akrab dengan Visual Basic-nya Microsoft,

Model View Controller

49

method ini mirip dengan penambahan karakter “&” agar muncul garis bawah pada suatu huruf pada label. Pada blok setting event handler, di sinilah tempat button-button diberi tugas untuk melakukan pekerjaannya ketika ia di-klik. Button
btnAddRow akan menambah suatu baris kosong pada tabel jika ia di-klik.

Karena yang ditambah adalah datanya, maka kita harus menggunakan tableModel untuk melakukan manipulasi proses ini. Di sini kita menggunakan method addRow ( Object newRow ), dan sebagai datanya kita masukkan sebuah String kosong. Action btnRemoveRow akan menghapus baris yang sedang terpilih. Pertama kita dapatkan nomor barisnya dengan method
getSelectedRow(), dan dengan tableModel, kita hapus baris tersebut

dengan method removeRow ( int row ). Kamu harus menambahkan error handling sendiri di sini, karena jika user meng-klik tombol ini tanpa memilih baris terlebih dahulu, maka Ini akan terjadi eksepsi method

ArrayIndexOutOfBoundsException.

disebabkan

getSelectedRow() mengembalikan nilai -1 jika baris tabel tidak ada yang

terpilih.
btnAddCol akan menambahkan kolom baru. tableModel bisa

melakukan ini dengan gemilang dengan memanggil method addColumn
( Object newCol ). Kamu bisa melakukan pengisian data pada kolom

ini secara langsung dengan mengoverload method ini dengan memanggil method tableModel.addColumn( Object newCol, Vector colData ), atau method tableModel.addColumn ( Object newCol, Object[]
colData ).

Button yang belum kita bahas adalah btnRemoveCol. Mekanisme dalam meremove kolom cukup panjang. Pertama kita dapatkan column model dengan method getColumnModel(). Kemudian kita dapatkan kolom yang sedang terpilih dengan getSelectedColumn(). Kedua method di atas milik JTable. Dengan columnModel.getColumn ( int
selectedCol ),

kita

dapatkan

instans

TableColumn

yang

50

Secangkir Kopi Java

merepresentasikan kolom yang akan kita hapus. Terakhir, kita remove kolom tersebut dengan method removeColumn ( TableColumn tc ). Saat yang menyenangkan… mari kita lihat hasil kerja jari-jari kita di atas keyboard!

Gambar 2.4 – Ada empat button di situ yang di dalamnya terdapat TableModel untuk melakukan manipulasi data.

CellRenderer dan CellEditor Sel pada JTable digambar dengan sebuah cell renderer dan pengeditannya dilakukan dengan sebuah cell editor. Secara umum, JTable merender selnya dengan JLabel dan menggunakan JTextField sebagai cell editornya. Sudah kita ketahui bahwa JTable bisa dimasuki data bertipe Object, artinya apapun bisa masuk ke JTable. Berikut ini adalah tampilan JTable secara default dari beberapa tipe data:

Class
Object Date Number ImageIcon Boolean

Renderer
JLabel JLabel JLabel JLabel JCheckBox

Alignment Rata kiri Rata kanan Rata kanan Rata tengah Rata tengah

Editor
JTextField JTextField JTextField

JCheckBox

Model View Controller

51

VC++. import java.table. "Attribute"}.URL. dll.*.swing. import javax.awt. ataupun Qt.io.*.*. MyTableModel tableModel = new MyTableModel ( tableData. "Last Modified". bisa diisi macam-macam. Listing 2. package galih.util. import java. import javax. import java.Sekarang. } //inisialisasi tabel dan melakukan createGUI private void init() { //table properties String[] tableHeader = { "T". Size.*.7 – Class ini berusaha mendapatkan daftar file dari suatu folder dan menampilkan atribut-atributnya seperti Nama. public class TableRendererDemo extends JFrame { //instance private JTable table. "Size". "Name".net.swing.swing. tableHeader ). table = new JTable ( tableModel ). import java. init (). dan yang tak pernah ditemukan pada tool IDE bahasa lain seperti VB. "Hidden". Last Modified. kita akan coba membuat suatu JTable yang benar-benar gila. 52 Secangkir Kopi Java . lain daripada yang lain. //konstruktor public TableRendererDemo() { super ( "Table Cell Renderer and Editor Demo" ).*. Object[][] tableData = getData ( "F:/My Documents" ).

setWidth ( 90 ).7 – Class ini berusaha mendapatkan daftar file dari suatu folder dan menampilkan atribut-atributnya seperti Nama. table. TableColumn tc3 = table.setMinWidth ( 120 ). Size. //lebar dari masing2 kolom TableColumn tc0 = table. tc3.setMinWidth ( 80 ).table. "Read Only". tc4.getColumn ( "Attribute" ).getColumn ( "T" ). TableColumn tc4 = table. DefaultCellEditor cellEditor = new DefaultCellEditor ( cmbAttribute ). tc0.setMaxWidth ( 100 ).setRowHeight( 19 ).setWidth ( 25 ). tc4. tc2.getColumn ( "Last Modified" ). tc3.setMinWidth ( 25 ). tc2. TableColumn tc2 = table.setWidth ( 35 ). Listing 2. tc2. tc4.getColumn ( "Size" ). //set cell editor pada kolom attribute dengan //JComboBox String[] comboData = { "Archive". tc3. dll.setCellEditor( cellEditor ). "Encrypted" }.setShowVerticalLines ( false ).setMaxWidth ( 135 ).setPreferredWidth ( 135 ).setMinWidth ( 30 ). Last Modified. Model View Controller 53 .setMaxWidth ( 25 ).setMaxWidth ( 60 ). JComboBox cmbAttribute = new JComboBox ( comboData ). tc4. tc0. tc0.

i < children. //ambil data satu per satu. Listing 2.length][6]. //nama file data[i][1] = children[i]. Object[][] data = new Object[children. icon data[i][0] = ( children[i].isDirectory () ) ? folderIcon : fileIcon. dll.CENTER ). 300 ). //icon URL folderPath = getClass (). true ). i++ ) { //file type.getName (). setVisible ( true ). } //mendapatkan data dari file public Object[][] getData( String folder ) { //daftar folder yang dikirim File file = new File ( folder ). setSize ( 600. URL filePath = getClass ().listFiles ().png" ). Last Modified. false ). Size.getResource ( "file.//pasang pada container Container cp = getContentPane(). setDefaultCloseOperation ( EXIT_ON_CLOSE ).getResource ( "folder.length. cp.add( new JScrollPane ( table ).7 – Class ini berusaha mendapatkan daftar file dari suatu folder dan menampilkan atribut-atributnya seperti Nama. MyImageIcon folderIcon = new MyImageIcon ( folderPath.png" ). MyImageIcon fileIcon = new MyImageIcon ( filePath. masukkan ke array data for ( int i = 0. File[] children = file. BorderLayout. 54 Secangkir Kopi Java .

} //mendapatkan tanggal yang bisa terbaca manusia. //karena Date berbentuk miliseconds private String getDate( Date date ) { Calendar calendar = Calendar.getInstance ().length (). dll. if ( dateOfMonth.length () == 1 ) month = "0" + month.get ( Calendar. data[i][2] = display.DAY_OF_MONTH ) ). if ( month. //hidden or not?? data[i][4] = ( children[i].//size //ini dalam bytes long fileSize = children[i].valueOf ( calendar.setTime ( date ).MONTH ) + 1. Last Modified. calendar.get ( Calendar. Model View Controller 55 . } return data. //bentuk kilo bytes String display = fileSize + " KB".isHidden () ) ? new Boolean ( true ) : new Boolean ( false ). //last modified data[i][3] = getDate ( new Date ( children[i]. //attribute data[i][5] = ( children[i]. fileSize /= 1024. Size. String dateOfMonth = String. } int month1 = calendar. String month = String.valueOf ( month1 ).lastModified () ) ).7 – Class ini berusaha mendapatkan daftar file dari suatu folder dan menampilkan atribut-atributnya seperti Nama.length () == 1 ) { dateOfMonth = "0" + dateOfMonth. Listing 2.canWrite () ) ? "Archive" : "Read Only".

} String day = "".AM_PM ) == Calendar.get ( Calendar.valueOf ( calendar. } //launcher public static void main ( String[] args ) { new TableRendererDemo().MINUTE ) ). if ( minutes.YEAR ). String shortYear = String. Last Modified.int year = calendar. 56 Secangkir Kopi Java . if ( calendar. } String minutes = String.AM ) { day = "AM".length () == 1 ) { minutes = "0" + minutes.substring ( 2 ).7 – Class ini berusaha mendapatkan daftar file dari suatu folder dan menampilkan atribut-atributnya seperti Nama.length () == 1 ) { hour = "0" + hour. String hour = String.get ( Calendar. } return dateOfMonth + "/" + month + "/" + shortYear + " " + hour + ":" + minutes + " " + day. dll. } } Listing 2.HOUR ) ). Size.get ( Calendar.get ( Calendar.valueOf ( year ).valueOf ( calendar. if ( hour. } else { day = "PM".

Last Modified. Model View Controller 57 . private String[] name. this. int col ) { return data[row][col]. Size.7 – Class ini berusaha mendapatkan daftar file dari suatu folder dan menampilkan atribut-atributnya seperti Nama. } //mendapatkan nilai pada baris dan kolom tertentu public Object getValueAt( int row. String[] name ) { this. } //mendapatkan class dari kolom public Class getColumnClass( int c ) { return getValueAt ( 0.length. untuk membuat table model //sendiri. karena kita perlu mengover-ride method //isCellEditable class MyTableModel extends AbstractTableModel { private Object[][] data.getClass ().name = name. dll.//package class MyTableModel. } //mendapatkan nama kolom public String getColumnName( int column ) { return name[column].length. //konstruktor public MyTableModel( Object[][] data. } //mendapatkan jumlah baris public int getRowCount() { return data.data = data. } //mendapatkan jumlah kolom public int getColumnCount() { return name. c ). } Listing 2.

Class di atas ( Listing 2.. public boolean isDirectory. kapan seneng-senenge?!?! ). well. jangan protes melulu.. int col ) { //override method ini agar bisa di set tidak bisa //diedit untuk kolom 3 dan kolom yang memiliki class //ImageIcon //get class Class columnClass = getColumnClass ( col ). untuk menambahkan identifier //bahwa suatu icon merupakan icon untuk folder atau file class MyImageIcon extends ImageIcon { private URL url.7 ) berusaha menampilkan daftar file dan folder yang ada pada folder F:\My Documents. puanjang buanget Lih?!?! Ah. return columnClass != ImageIcon. this. int row. dll. Last Modified. ( Weleh.isDirectory = isDirectory. } } //package class MyImageIcon.class && col != 3. public MyImageIcon( URL url. Kenapa kita perlu membuat 58 Secangkir Kopi Java . boolean isDirectory ) { super ( url ).7 – Class ini berusaha mendapatkan daftar file dari suatu folder dan menampilkan atribut-atributnya seperti Nama. Well.url = url. tak mengapa. } //memberi nilai pada baris dan kolom tertentu public void setValueAt( Object aValue. Class MyTableModel adalah subclass dari AbstractTableModel. mari kita bahas perlahan-lahan secara sistematik. this. Oke oke. untuk latihan kita memang perlu bersakit-sakit dahulu.. } } Listing 2. well. Size... bersenang-senang kemudian.public boolean isCellEditable( int row. int column ) { data[row][column] = aValue.

Blok yang sedikit rumit terjadi pada data Last Modified. Untuk menampilkannya dalam Kilo Bytes. Sekarang kita melihat method getData ( String folder ). Kamu harus menambahkan error handling di sini. kita perlu membaginya dengan 1024. Kemudian file tersebut kita daftar dengan method listFiles() yang mereturn array File.isDirectory() ) { data[i][0] = folderIcon. Proses yang dilakukan pertama adalah menjadikan parameter String folder menjadi sebuah file. } Method length() akan mereturn ukuran file long integer dalam satuan bytes. Mungkin statement seperti data[i][0]=(children[i]. } else { data[i][0] = fileIcon. maka kita harus mengoverride method isCellEditable ( int row. Apa error handlingnya? Bisa kamu tebak sendiri? Kemudian kita menyiapkan icon untuk folder dan file.table model sendiri? Nantinya kita akan menampilkan icon folder dan tanggal Last Modified yang tidak bisa diedit oleh user ( read only ). ( 1 KB = 1024 bytes ). Kita menyiapkan data untuk tabel lewat method ini. Method lastModified() akan mereturn waktu terakhir file dimodifikasi dalam Model View Controller 59 . int col ) sesuai dengan kebutuhan kita.isDirectory())?folderIcon:fileIcon. Itu sebenarnya sama saja dengan blok ifelse seperti ini: if ( children[i]. Kita memasuki blok looping untuk memasukkan data satu persatu. Di sini aku men sub classkan ImageIcon menjadi MyImageIcon untuk menambahkan nilai boolean isDirectory untuk membedakan icon folder atau file. Karena secara default JTable adalah full editable. cukup membingungkan bagimu. Masih di method getData ( String folder ).

kita memakai class Calendar.getInstance(). sebagian besar method milik class Date telah di deprecated. yaitu getColumn ( Object identifier ). Sejak JDK 1. Ingat path “F:\My Documents” harus kamu ganti sesuai dengan yang ada di kompie kamu. kita mengatur lebar dari masing-masing kolomnya dengan TableColumn.1. kita masukkan ke class DefaultCellEditor ( JComponent component ). Sebagai gantinya. kita menggunakan method-nya JTable. dan terakhir: menulis kode launchernya! Apa lagi kalau bukan method sakti public static void main ( String[] args ). Untuk mendapatkan instance dari TableColumn. aplikasi ini hanya sekedar membaca dari file dan sama sekali tidak melakukan penulisan ke file. Kemudian method setTime ( Date date ) akan menset Calendar menjadi waktu kapan file terakhir dimodifikasi. membuatnya visible. Jadi kamu nggak usah kuatir akan dokumen-dokumen kamu. 60 Secangkir Kopi Java . Dari situ kita tinggal mengatur tampilan tanggalnya sesuai dengan keinginan kita dengan method get ( int constant ). Aku perlu mendemokan cell editor di sini. Dan dari TableColumn. Di sini aku menggunakan JComboBox sebagai editor dari kolom Attribute. Kita perlu mereparasinya agar menjadi bentuk yang lebih enak dibaca dalam method getDate ( Date date ). Class ini tidak dapat diinstantiated secara langsung. Setelah kita melakukan inisialisasi tabel dan datanya. Setelah kita siapkan JComboBox lengkap dengan datanya. Hal kecil yang perlu dilakukan adalah memasang ke dalam container.. Well.mili seconds. Mari kita pelototi method getDate ( Date date ). Kembali ke method init(). Constant lengkapnya bisa kamu lihat di dokumentasi javadoc dari class Calendar. menentukan apa yang terjadi jika tombol [x] pada window dipencet. Kita mendapatkan instance dari Calendar dari Calendar. menentukan ukuran window. kita menset class tersebut sebagai cell editor dari kolom dengan method setCellEditor ( CellEditor cell ).

JTree adalah komponen yang paling sulit dimengerti.5 – Asyik nggak? Ada Combo Box di dalam sel tabel. DefaultTreeModel. Ada Checkbox dan iconnya lagi!!! iii. Ketika JTree menampilkan sebuah tree. dan TreePath. DefaultTreeCellRenderer.swing dan class-class pendukungnya berada di package javax. Komponen-komponen pendukung tersebut antara lain DefaultMutableTreeNode. makanya aku taruh di bagian akhir dari bab ini.Gambar 2. JTree Tinggal satu lagi komponen Model-View Controller yang kurasa penting untuk dibahas. Model View Controller 61 . JTree adalah komponen yang kompleks. ataupun memodifikasi bapak ataupun anak dari suatu node.swing. seperti membuat node baru. komponen Swing yang menyajikan data secara hierarki seperti pohon. Dan menurutku.tree. Dia adalah JTree. JTree sendiri berada di package javax. yang bisa di-expand dan di-collapse. TreeSelectionModel. Contoh yang paling baik untuk menjelaskan JTree adalah hirarki folder yang digambarkan oleh Windows Explorer. representasi data dipegang oleh class DefaultMutableTreeNode. DefaultTreeCellEditor. letaknya di sebelah kiri.

62 Secangkir Kopi Java .4. TreeModel tidak secara langsung mengatur dan memodifikasi data. juga untuk memasang customized icon untuk setiap nodenya. DefaultMutableTreeNode kemudian membuat untuk instans merepresentasikan DefaultTreeModel yang sesuai dengan root. Class TreeSelectionModel menghandle pemilihan node tree. Untuk membuat sebuah tree model. DefaultTreeModel mengandle seluruh tree.Ketika DefaultMutableTreeNode merepresentasikan sebuah node. pertama kamu harus membuat root instans dari tree. Data dari tree diatur oleh class DefaultMutableTreeNode. Class DefaultTreeCellRenderer menyediakan mekanisme untuk merender node tree sebagai sebuah label. DefaultTreeCellEditor digunakan untuk melakukan pengeditan pada node tree dengan sebuah JTextField.6 – Contoh JTree dalam demo SwingSet2 bawaan langsung dari J2SE 1. Gambar 2. Tidak seperti ListModel dan TableModel. Dan class TreePath adalah class pendukung yang merepresentasikan suatu node dalam suatu path.1 ( dulu dikenal dengan sebutan JDK – Java Developer’s Kit ). misalnya.

package galih.*.awt. ataupun TreeModel.First Run! JTree tidak mendukung scrolling secara langsung.swing.swing.swing. Kamu bisa menggunakan Array. Ada beberapa konstruktor JTree. private JButton btnRemove = new JButton("Remove Node").event. Hmm…. public class JTreeDemo extends JFrame { //instans private JTree tree. private DefaultTreeModel treeModel. kita langsung ke kodenya.*. import java. karena sebenarnya JTree itu ramah sekali – tampangnya aja yang kriminil. import javax.8 – Untuk first run. import javax. Vector. maka yang terjadi adalah tampilan JTree secara default. import java.*. private DefaultMutableTreeNode rootNode. Kamu perlu memasukkannya dalam JScrollPane untuk mendapatkan dukungan scrolling. Semua parameter konstruktor JTree merupakan data yang akan ditampilkan.tree. } Listing 2.awt. Jika kamu menggunakan konstruktor kosong dari JTree. kedengarannya menakutkan ye? Supaya tidak terlalu menakutkan. //konstruktor public JTreeDemo() { super( "Default Tree Demo" ).*. private JButton btnAdd = new JButton( "Add Node" ). setEventHandler(). createGUI(). rasanya kode di atas terlalu ruwet yach??? Model View Controller 63 .

8 – Untuk first run.add( btnRemove ). panel. contPane.add( panel.setMnemonic( 'R' ).addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { removeNode(). } Listing 2. btnRemove. //pasang pada container JPanel panel = new JPanel( new FlowLayout() ). setDefaultCloseOperation( EXIT_ON_CLOSE ). } //create graphical user interface private void createGUI() { //root node rootNode = createTree(). setSize( 400.NORTH ). BorderLayout. //tree model treeModel = new DefaultTreeModel( rootNode ).add( btnAdd ). Container contPane = getContentPane(). btnRemove.setMnemonic( 'A' ). panel. 300 ). setVisible( true ). tree = new JTree( treeModel ).CENTER ). rasanya kode di atas terlalu ruwet yach??? 64 Secangkir Kopi Java . BorderLayout. } } ).//set event handler di sini private void setEventHandler() { btnAdd. contPane.add( new JScrollPane( tree ). } } ). btnAdd.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { addNode().

if ( node != null ) { treeModel. treeModel. showInputDialog( this.removeNodeFromParent( node ). } //create tree private DefaultMutableTreeNode createTree() { //root node DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode( "Penyanyi" ). parent. getLastSelectedPathComponent(). } //remove node public void removeNode() { //dapatkan node terpilih DefaultMutableTreeNode node = ( DefaultMutableTreeNode ) tree. if ( parent == null ) return.insertNodeInto( new DefaultMutableTreeNode( name ). Listing 2. } } //add node public void addNode() { //dapatkan node terpilih DefaultMutableTreeNode parent = ( DefaultMutableTreeNode ) tree. getLastSelectedPathComponent().getChildCount() ). "Nama Node: " ). String name = JOptionPane. rasanya kode di atas terlalu ruwet yach??? Model View Controller 65 .//launcher public static void main( String[] args ) { new JTreeDemo().8 – Untuk first run. parent.

rockNode. DefaultMutableTreeNode femaleNode = new DefaultMutableTreeNode( "Fantastic Female" ).add( new DefaultMutableTreeNode( "Boomerang" ) ).add( new DefaultMutableTreeNode( "Metallica" ) ). femaleNode.add( new DefaultMutableTreeNode( "Padi" ) ).8 – Untuk first run.add( new DefaultMutableTreeNode( "Agnes Monica" ) ). bandNode. rockNode.add( new DefaultMutableTreeNode( "Krisdayanti" ) ). femaleNode.add( new DefaultMutableTreeNode( "Nirvana" ) ). femaleNode. bandNode.add( new DefaultMutableTreeNode( "Alda" ) ).add( bandNode ). bandNode. rootNode.//child node DefaultMutableTreeNode bandNode = new DefaultMutableTreeNode( "Band" ). rockNode. DefaultMutableTreeNode rockNode = new DefaultMutableTreeNode( "Rock" ). Listing 2. rasanya kode di atas terlalu ruwet yach??? 66 Secangkir Kopi Java .add( new DefaultMutableTreeNode( "B I P" ) ). bandNode.add( new DefaultMutableTreeNode( "ADA Band" ) ). rockNode.add( new DefaultMutableTreeNode( "Godbless" ) ).add( new DefaultMutableTreeNode( "Bon Jovi" ) ).add( rockNode ). bandNode.

Setiap node merupakan satu objek class dari DefaultMutableTreeNode. Setelah kita dapatkan node yang akan dihapus.add( femaleNode ). Yang dilakukan adalah mendapatkan node yang terpilih dengan method getLastSelectedPathComponent(). rootNode. kita perlu tiga langkah. return rootNode. Dalam melakukan inisialisasi JTree. kemudian membuat instans DefaultMutableTreeNode dan ditambahkan ke node parent. kita meminta user memasukkan nama node. pertama mendapatkan data lewat method createTree() yang mereturn DefaultMutableTreeNode. JTree bisa di-inisialisasi. seperti biasa. Method createTree() membuat node-node secara satu per satu. mari kita menuju method createGUI() dulu. rasanya kode di atas terlalu ruwet yach??? Well. Node akan langsung hilang tanpa bekas! Model View Controller 67 . } } Listing 2. maka kita tidak melakukan apa-apa. Method addNode() akan dipanggil ketika tombol btnAdd di-klik. Tetapi jika tidak null. Jika return value-nya null. kita tinggal memanfaatkan DefaultTreeModel ( untuk memanggil node method removeNodeFromParent MutableTreeNode ).femaleNode. Method removeNode() lebih sederhana daripada method addNode().add( new DefaultMutableTreeNode( "Nike Ardilla" ) ). Kita harus melakukan explicit casting di sini karena method tersebut mereturn Object. Method add ( DefaultMutableTreeNode childNode ) akan menjadikan node pemanggil method tersebut menjadi parent dari node yang ada di dalam parameter method tersebut.8 – Untuk first run. Dari situ kita bentuk DefaultTreeModel. Setelah model selesai.

node yang tertutup ( collapsed ). BBS-ku memakai Java Applet dan koneksi databasenya memakai MySQL JDBC-Native-Connection. Sampai sekarangpun kabut yang menutupi JTree di depan mataku belum sepenuhnya terkuak. Dia juga mengatur warna foreground dan background dari setiap node. yang diimplementasikan oleh class DefaultTreeCellRenderer. Aku menggunakan komponen ini untuk sebuah aplikasi tiruan BBS FTIF ( kampusku ) – jika BBS FTIF memakai Visual Basic dan pure ActiveX Control Data Object Database ( ADODB ). Interface TreeCellRenderer mendefinisikan bagaimana sel dirender. Tree Cell Renderer dan Tree Cell Editor Seperti halnya komponen Swing tingkat tinggi lainnya.Gambar 2.7 – Hasil dari first run kita terhadap JTree Aku mengenal JTree untuk pertama kalinya sekitar bulan Januari 2004. JTree juga memiliki cell renderer. 68 Secangkir Kopi Java . dan node yang terbuka ( expanded ). Class ini mengatur icon-icon untuk node leaf.

Kamu bisa memakai JTextField.setClosedIcon ( closedImageIcon ). Jika properti editable pada JTree di-set true.setCellEditor ( new DefaultCellEditor ( cmbEditor ) ). Tapi jika kamu memakai lingkungan MetalLookAndFeel. Node JTree diedit jika suatu node diklik tiga kali ( sekali untuk seleksi.addItem ( “Juelek Sekali” ). cmbEditor. Model View Controller 69 . jTree.setBackgroundSelectionColor ( Color. Untuk membuat editor sendiri.getCellRenderer().addItem ( “Lumayan” ).addItem ( “Bagus” ). //icon untuk leaf render. Icon-icon untuk JTree secara default bergantung pada lingkungan sistem operasi – jika kamu menggunakan dependent Look And Feel.setLeafIcon ( leafImageIcon ). Contohnya seperti di bawah ini: //editor JComboBox cmbEditor = new JComboBox(). cmbEditor. render.Kita bisa melakukan override terhadap method-method DefaultTreeCellRenderer seperti di bawah ini: DefaultTreeCellRenderer render = ( DefaultTreeCellRenderer ) jTree. //icon expanded node render.setEditable ( true ). icon-icon untuk JTree independen terhadap sistem operasi. secara default cell editornya adalah JTextField.blue ). dua kali untuk membuka node ). JComboBox.setOpenIcon ( openImageIcon ). Tetapi JTree secara default sama sekali tidak editable. jTree. //collapsed node render. JTree juga memiliki cell editor. Class ini sama persis dengan editornya JTable. kamu bisa melewatkannya melalui konstruktor class DefaultCellEditor. cmbEditor. maupun JCheckBox untuk editornya.

JTree akan memanggil event TreeExpansionEvent. Ketika suatu node pada JTree dipilih. jTree. new DefaultCellEditor ( cmbEditor ) ). JTree akan memanggil event TreeSelectionEvent. Tree Event Ada dua event penting yang berhubungan dengan JTree. Mereka adalah TreeSelectionEvent dan TreeExpansionEvent. editor akan muncul dalam satu klik mouse dan meng-overlap si icon. yaitu seperti ini: DefaultTreeCellEditor editor = new DefaultTreeCellEditor ( jTree. yang berisi satu method. Ada alternatif yang lebih baik untuk pemasangan editor. treeExpanded Sebagai menu penutup JTree. new DefaultTreeCellRenderer(). Bisakah kamu mengetahuinya? ( Tidak? Yaa dicoba donk mbaak ). Listener pemilihan node harus mengimplementasikan interface TreeSelectionListener. Baca bismillah dulu… 70 Secangkir Kopi Java . treeCollapsed(TreeExpansionEvent (TreeExpansionEvent e). yaitu valueChanged ( TreeSelectionEvent e ). Ketika suatu node dibuka ( expanded ) atau ditutup ( collapsed ).Pengesetan editor dengan di atas terdapat masalah kecil. Masalahnya. yang mencoba mengakses file system dalam hardisk kita.setCellEditor ( editor ). Listener yang menghandel pembukaan atau penutupan node harus yang mengimplementasikan berisi e) interface yaitu TreeExpansionListener dua dan method. kita akan mencoba membuat tiruan hierarki folder pada Windows Explorer dengan tree model buatan kita sendiri.

listFiles().swing. String[] children = dir.9 – FileSystemModel merupakan model untuk JTree yang menggambarkan hierarki file dan folder pada File System kita. import java.root = root. Model View Controller 71 .event.tree. import javax.package galih. } //get root public Object getRoot() { return root.*.swing.*.tree. import java.*. //listener private Vector listeners = new Vector(). import javax.list(). } //get child public Object getChild( Object parent. public class FileSystemModel implements TreeModel { //root private File root. } //get child count public int getChildCount( Object parent ) { File file = ( File ) parent.io.*. //constructor public FileSystemModel( File root ) { this. if ( file.*.swing.swing. return new TreeFile( dir. int index ) { File dir = ( File ) parent. Listing 2.isDirectory() ) { File[] fileList = file. children[index] ).util. import javax.

if ( fileList != null ) { int counter = 0. } return counter. } //is leaf? public boolean isLeaf( Object node ) { File file = ( File ) node.9 – FileSystemModel merupakan model untuk JTree yang menggambarkan hierarki file dan folder pada File System kita.getLastPathComponent().getName(). return file.isFile().getParent(). } //get numeric index of child node public int getIndexOfChild( Object parent.length. } } return 0. File file = ( File ) child.list(). } //value of object changes public void valueForPathChanged( TreePath path. Object child ) { File dir = ( File ) parent. for ( int i = 0. String[] children = dir. 72 Secangkir Kopi Java . Listing 2. Object value ) { //prepare to rename file File oldFile = ( File ) path. i < children.equals( children[i] ) ) { return i.length. i++) { counter++. } } return -1. String parent = oldFile. i++ ) { if ( file. for (int i = 0. i < fileList.

iterator().. changedChild ).treeNodesChanged( event ). } //hai-hai. private void fireTreeNodesChanged( TreePath path. Model View Controller 73 . File parentFile = new File( parent ). TreeModelListener treeListener = null.next(). fireTreeNodesChanged( path. treeListener. newValue ). //sending event to each listener while ( iterator. int[] childIndices = { getIndexOfChild( parentFile.hasNext() ) { treeListener = ( TreeModelListener ) iterator. path. target ) }. Object[] child ) { TreeModelEvent event = new TreeModelEvent ( this. node ada yang berubah lhoo. Iterator iterator = listeners. Object[] changedChild = { target}. child ). childIndices. } } Listing 2.String newValue = ( String ) value.9 – FileSystemModel merupakan model untuk JTree yang menggambarkan hierarki file dan folder pada File System kita. int[] indices. indices. oldFile.renameTo( target ).getParentPath().. //renaming file File target = new File( parent.

String child ) { super( parent. } public TreeFile( File parent. susunan file pada file system memiliki hierarki tertentu sehingga mudah untuk ditampilkan pada JTree. child ). } //inner class private class TreeFile extends File { public TreeFile( File parent.remove( listener ).public void addTreeModelListener( TreeModelListener listener ) { listeners. suatu syarat mutlak class yang ingin menjadi model dari JTree. Oce. class di atas ( Listing 2. } public void removeTreeModelListener( TreeModelListener listener ) { listeners. karena jika menggunakan class default.9 – FileSystemModel merupakan model untuk JTree yang menggambarkan hierarki file dan folder pada File System kita. Kita harus membuat implementasi sendiri pada kasus ini.add( listener ).toString() ). } } } Listing 2.9 ) merupakan implementasi dari interface TreeModel. child. 74 Secangkir Kopi Java . } public String toString() { return getName().?!? ). File child ) { super( parent. kita akan terlalu kesulitan ( ingat DefaultMutableBlaBlaBla…. Apalagi.

kita return nilai -1. Jika file adalah sebuah direktori. kita panggil method listFiles() yang akan mereturn array File. kita return nilai index dari looping. kita return nilai 0 yang menunjukkan bahwa parent tidak memiliki anak. dengan looping. Method ini mereturn sebuah object inner class TreeFile yang mengoverride method toString-nya class File untuk mereturn nama dari file tersebut. Maka kita tinggal mereturn true jika node adalah leaf ( file ) dan false jika bukan leaf ( direktori ). Setiap objek bisa menjadi node dari JTree. Kita harus melakukan casting kepada parent dan child agar menjadi objek File. dalam hal ini adalah File. Jika tidak ketemu. Model View Controller 75 . kita mencari kesamaan antara tiap-tiap anggota children dengan child. JTree secara berulangulang memanggil method getChild ( Object parent. Nah. Jika file dari hasil casting bukan direktori. apakah interface itu? Interface hanyalah sebuah deklarasi dari method-method yang akan digunakan. Kita mendapatkan daftar anaknya parent dengan method list() yang mereturn array String children. Interface memungkinkan implementasinya. Object child ) berusaha mengetahui index dari child yang dimulai dari 0. Dari situ kita hitung berapa panjang array yang segera kita return-kan. Jika sama. so pasti programnya langsung error! Ketika membangun view dari TreeModel. JTree memanggil method isLeaf ( Object node ) untuk mengetahui apakah node mempunyai anak atau tidak. Interface sangat berguna ketika kita memerlukan sebuah objek. Method getChildCount ( Object parent ) akan mengembalikan jumlah dari anak yang dimiliki parent. namun implementasi nyatanya belum kita tulis. int index ). Method getIndexOfChild ( Object parent. Kemudian parent akan di-casting ke objek File.Sebenarnya. masih abstrak di awang-awang. kita menggunakan jika kita objek yang belum program ditulis tanpa Tetapi menjalankan implementasi interface itu.

*. Di sini kita akan benar-benar melakukan perubahan nama ( renaming ) file.*.swing. String name ).tree.*. dan objek node yang berubah itu sendiri.swing. Object value ) ketika user melakukan perubahan pada node. kita perlu mendapatkan induk dari file tersebut dan meng-casting value sebagai nama baru. import java. import java.awt.*. Kita harus memberitahu kepada semua listener bahwa ada node yang berubah dengan mengirim sebuah TreeModelEvent.awt. Semua listener kita simpan dalam Vector dan pemasukan dan pengeluarannya melalui gerbang method addTreeModelListener dan removeTreeModelListener.JTree akan memberitahu method valueForPathChanged ( TreePath path. Kita melakukannya pada method fireTreeNodesChanged. kita buat file baru dengan konstruktor File ( String parent. Bisa kamu lihat di Windows Explorer kalau nggak percaya! Setelah mendapatkan node file yang akan di-rename.tree.10 – Class ini menunjukkan hierarki pada file system dengan menggunakan JTree dan FileSystemModel yang telah kita tulis pada listing 2. Dari informasi induk dan nama file. Sekarang kita tinjau listing untuk menampilkan TreeModel pada listing 2.9 pada JTree dan menampilkannya pada layar monitor Windows ( apa Linux? ) tercinta… package galih. import java. import javax. import javax.9 76 Secangkir Kopi Java . array integer yang berisi index dari tiap-tiap node yang berubah. Kemudian oldFile kita ganti nama ke file baru dengan method renameTo ( File target ).swing.io.*.event. Listing 2. Yang kita perlukan untuk membuat sebuah TreeModelEvent adalah TreePath.

tree = new JTree( treeModel ). tree. } } ).getLeadSelectionPath(). //konstruktor public JTreeDemo2() { super( "JTree Demo ver. private JButton btnExpand = new JButton( "Expand" ).fireTreeCollapsed( path ). } private void init() { //init tree treeModel = new FileSystemModel( new File( "H:\\" ) ). 10 – Class ini menunjukkan hierarki pada file system dengan menggunakan JTree dan FileSystemModel yang telah kita tulis pada listing 2. } } ).getLeadSelectionPath(). tree.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { TreePath path = tree.fireTreeExpanded( path ).public class JTreeDemo2 extends JFrame { //instans private JTree tree.addActionListener(new ActionListener() { public void actionPerformed( ActionEvent e ) { TreePath path = tree. 02" ).setShowsRootHandles( true ). tree. setEventHandler(). } //event private void setEventHandler() { btnExpand. init(). Listing 2. private JButton btnCollapse = new JButton( "Collapse" ). private TreeModel treeModel.9 Model View Controller 77 . btnCollapse.

setMnemonic( 'C' ).setEditable( true ).add( btnCollapse ). Container contPane = getContentPane().png" ) ) ).//renderer DefaultTreeCellRenderer renderer = ( DefaultTreeCellRenderer ) tree. tree.getResource( "folder.png" ) ) ).getResource( "folder_open.add( btnExpand ). } Listing 2.getResource( "file. 10 – Class ini menunjukkan hierarki pada file system dengan menggunakan JTree dan FileSystemModel yang telah kita tulis pada listing 2. tree.NORTH ).setMnemonic( 'E' ). setSize( 300.add( panel. setDefaultCloseOperation( EXIT_ON_CLOSE ). renderer. 400 ). contPane. "Test!"}. BorderLayout.9 78 Secangkir Kopi Java . DefaultTreeCellEditor editor = new DefaultTreeCellEditor( tree. "Coba". btnCollapse.setOpenIcon( new ImageIcon( getClass(). setVisible( true ). getCellRenderer(). panel. new DefaultCellEditor( cmbEditor ) ). renderer.setLeafIcon( new ImageIcon( getClass(). //cell editor --klik 3 kali String[] comboData = { "Demo". renderer. JPanel panel = new JPanel( new FlowLayout() ). renderer.png" ) ) ). BorderLayout.CENTER ). panel. contPane. JComboBox cmbEditor = new JComboBox( comboData ).setClosedIcon( new ImageIcon( getClass(). btnExpand.setCellEditor( editor ).add( new JScrollPane( tree ).

Kemudian kita set JTree dengan TreeModel yang telah kita persiapkan. dan setClosedIcon untuk mengganti icon default menjadi icon kita. Method setEventHandler memberi nyawa pada JButton agar bisa membuka dan menutup JTree. kita memanggil method fireTreeCollapsed ( TreePath path ) dari path yang kita dapatkan. Di sini aku ke menggunakan kamu. kita menggunakan class DefaultTreeCellRenderer.9 Method init() melakukan inisialisasi JTree dengan membuat FileSystemModel terlebih dahulu. Aku memamerkan isi dari drive H:\ di kompie-ku. Jangan lupa untuk men-set JTree menjadi editable agar cell editor kita berguna. setOpenIcon. kita memanggil method fireTreeExpanded ( TreePath path ) setelah mendapatkan path dari method getLeadSelectionPath. } } Listing 2. tapi mengambil dari JTree dengan getCellRenderer() dan mengoverride method setLeafIcon. Dan untuk btnCollapse. Dalam menset cell renderer. Cell Editor yang kita gunakan adalah DefaultTreeCellEditor. Cara memasangnya di JTree sudah kubahas di awal sebelum kita berkoding.//launcher :) public static void main( String[] args ) { new JTreeDemo2(). Aku memasukkan event ini karena: inilah yang membuatku pusing selama dua minggu memikirkan bagaimana membuka node JTree secara otomatis pada Model View Controller 79 . Di sini kita tidak membuat renderer baru. Method setShowsRootHandles ( boolean show ) membuat icon kunci root node untuk membuka dan menutup node ditunjukkan atau tidak. 10 – Class ini menunjukkan hierarki pada file system dengan menggunakan JTree dan FileSystemModel yang telah kita tulis pada listing 2. Untuk btnExpand. Kamu JComboBox – hanya untuk menjadi menunjukkannya bisa menggantinya JTextField agar lebih manusiawi.

Ringkasan Pada bab ini. memanipulasinya dan menyajikannya secara rapi lewat komponen JList. jiwa dari komponen-komponen tersebut. kamu telah mempelajari komponen-komponen Swing yang cukup kompleks secara mendetail. kamu bisa mengatakan dengan sombong ke dirimu sendiri ( jangan ke orang lain! ). 80 Secangkir Kopi Java . ataupun JTree. awal liburan semester IV. Kamu juga telah mempelajari konsep model-view controller.akhir Juni 2004. dengan renderer dan editor yang full customized i. bagaimana menyimpan data. bahwa kamu telah Advanced dalam Java 2 Standard Edition. Jika kamu telah menguasai bab ini. JTable. khususnya Swing.8 – JTree yang menggambarkan file system. Dan jawabannya baru kudapatkan tadi malam ( 12 Agustus 2004 ) ketika aku menulis ini! Bagaimana hasilnya? Nih! Gambar 2. bagaimana membuat renderer dan editor sendiri untuk komponen-komponen tersebut.

java database connectivity [ jdbc ] Desember 2003 .

.

he. Kenapa aku mengatakan “setahuku”.. ( -. MySQL. Postgre sebenarnya juga mendukung. Sekilas Database Dunia pemrograman bagaikan sayur tanpa garam dan kuah ( wekk. Apalagi untuk Microsoft Access. Structured Query Language ( SQL ) SQL adalah bahasa standar untuk melakukan query kepada database. aku belum pernah menemukan driver langsung kecuali memakai ODBC. Kamu pasti akan menemui database jika aplikasi yang kamu tulis adalah sebuah sistem informasi. Karena bab ini tidak berjudul Database. Mengapa kok gitu Lih? Karena setiap aplikasi nyaris memerlukan database. dan Cloudspace dari Informix Software. SQL independen terhadap arsitektur database sehingga bisa digunakan kepada database apa saja.).. Sistem Informasi sendiri merupakan bagian yang sangat kompleks. juga bukan database.. he. aku tidak akan membahas konsep basis data secara mendetail.. toh aku juga nggak bisa ngonsep. bahwa Sistem Informasi bukanlah Teknologi Informasi.he. Mereka adalah Oracle . merupakan gabungan antara software dan hardware dan lingkungan ( wuihh. namanya bukan sayur kalo gitu ) jika tidak melibatkan database. Tapi harap diingat. Suetuju?!?! Setahuku... Java Database Connectivity [ JDBC ] 83 . ). ada beberapa DBMS ( Database Management System ) yang mendukung Java secara langsung. tapi aku tak pernah memakainya. Sedangkan untuk MS-SQLServer 2000 aku memerlukan driver dari third party ( Borland ).i. karena aku hanya pernah menggunakan driver JDBC-NativeAPI untuk tiga DBMS tersebut. sok teu banget aku -. Aku akan langsung ke bagaimana memanipulasi database dengan Java. apalagi Microsoft Access..semoga anak SI ga ada yang baca ini ye. bukaaan.

aku akan menggunakan database AkademikPIKTI. Sebagai contoh. yang kudapat dari kuliah Basis Data-nya Pak Imam K semester III kemarin.SELECT Syntax lengkap dari SQL – SELECT adalah: SELECT [DISTINCT] select_list FROM table_source [WHERE search_condition] [GROUP BY group_by_expression] [HAVING search_condition] [ORDER BY order_expression [ASC | DESC] ] Menurut kuliahku Basis Data dulu. dan yang berada di dalam tanda [ ] boleh disertakan atau tidak sesuai dengan kebutuhan. yang berhuruf kecil merupakan isian yang bisa diubah sesuai dengan kebutuhan kita. yang harus disertakan jika kita membutuhkan pengolahan data.1 – Relationship yang dipakai dalam database AkademikPIKTI 84 Secangkir Kopi Java . Gambar 3. arti huruf besar adalah keyword.

Gambar 3. nama kolom harus berada dalam tanda [ ]. sehingga misalnya menjadi [ dosen killer ]. Artinya hasil query yang sama ditampilkan sekali. Kriteria tersebut dimasukkan dalam klausa WHERE. Untuk menampilkan kolom yang spesifik. Kita perlu melakukan filter agar yang tampil sesuai dengan kriteria yang diperlukan. peminjam boleh meminjam lebih dari satu kali.2 – Hasil Query dengan filter WHERE Java Database Connectivity [ JDBC ] 85 . misalnya SELECT nip. Misalnya dalam database Perpustakaan. ). ganti tanda asterisk ( * ) menjadi nama kolom. nama FROM mahasiswa WHERE jeniskel = 'L' Dia akan menampilkan semua nrp dan nama mahasiswa yang berjenis kelamin laki-laki.SQL minimal contohnya seperti ini: SELECT * FROM dosen Dia akan menampilkan seluruh kolom pada tabel dosen. nama FROM dosen Perhatikan jika nama kolom terdapat spasi. kita tidak cukup melakukan query dengan memilih semua baris. Contoh: SELECT nrp. dipisahkan dengan tanda koma ( . Peminjam yang meminjam lebih dari satu kali akan ditampilkan sekali jika query kita: SELECT DISTINCT no_pinjam FROM peminjam WHERE Pada kebanyakan kasus. [ DISTINCT ] digunakan untuk menghilangkan duplikasi pada query.

<. suatu nilai yang belum diisi nilai atau kosong. meskipun ada hal-hal kecil yang berbeda. >=.Ada beberapa operasi yang digunakan untuk melakukan filtering. <=. 3) 86 Secangkir Kopi Java . IS Untuk operasi IS. >. <> atau !=. Operasi ini pada umumnya sama untuk semua DBMS. • Operasi LIKE Operasi ini khusus untuk tipe data string. • Operasi Perbandingan: =. Contoh: Menampilkan koleksi yang jenisnya buku dan majalah (idTipeKoleksi=1 atau 2): SELECT * FROM koleksi WHERE idTipeKoleksi IN (1. Null tidak sama dengan 0. Simbol _ mewakili satu dari sembarang karakter Contoh: Menampilkan nama mahasiswa yang memiliki nama depan Budi: SELECT * FROM mahasiswa WHERE nama LIKE “Budi%” Menampilkan nama mahasiswa yang memiliki nama dengan huruf ketiga d. 2) Menampilkan anggota yang selain mahasiswa atau dosen (idJenisAnggota selain 2 dan 3) SELECT * FROM anggota WHERE IDJenisAnggota NOT IN ( 2. operasi ini membandingkan dengan kumpulan nilai. yang diisikan adalah null. SELECT * FROM mahasiswa WHERE nama LIKE “__d” • Operasi IN dan NOT IN Seperti arti keyword-nya. Kumpulan nilai ini bisa berupa nilai-nilai yang diisikan ataupun query tunggal ( query yang hasilnya hanya satu kolom saja ). Simbol yang digunakan: simbol % mewakili 0 – tak terhingga dari sembarang karakter. ataupun “” ( String kosong ). Operasi ini digunakan untuk mengenali string yang memiliki pola tertentu.

<kolom 2> ] Klausa ini digunakan untuk mengelompokkan fungsi-fungsi agregate.Menampilkan anggota yang belum pernah meminjam buku sama sekali: SELECT * FROM anggota WHERE id NOT IN (SELECT DISTINCT idAnggota FROM Peminjaman) FUNGSI AGREGATE Fungsi ini hasilnya diambil dari proses tiap baris pada tabel. • AVG ( kolom ) untuk mendapatkan nilai rata-rata pada suatu kolom. Contoh: Untuk menampilkan jumlah seluruh anggota: SELECT COUNT(*) FROM Anggota Untuk menampilkan tahun kelahiran anggota tertua: SELECT MIN( year ( TglLahir ) ) FROM anggota GROUP BY <kolom 1> [. • MIN ( kolom ) untuk mendapatkan nilai terendah pada suatu kolom. • SUM ( kolom ) untuk mendapatkan jumlah keseluruhan dari suatu kolom. Contoh: Untuk menampilkan jumlah anggota perjenis kelamin: SELECT JK. AVG(harga) FROM koleksi GROUP BY idPenerbit Java Database Connectivity [ JDBC ] 87 . Proses tersebut akan mengolah nilai sebuah field atau lebih mulai baris pertama sampai seluruh baris. Fungsi-fungsi tersebut yaitu: • COUNT ( * ) untuk mendapatkan jumlah baris. COUNT(*) FROM anggota GROUP BY JK Untuk menampilkan rata-rata harga koleksi per kode penerbit SELECT idPenerbit. • MAX ( kolom ) untuk mendapatkan nilai tertinggi pada suatu kolom.

Maka aku perlu menyertakan hasil latihan SQL-ku bersama kuliahnya Pak Imam di sini. SQL Language adalah case insensitive. Jadi kamu boleh menulis SELECT. select. Ini adalah WHERE-nya fungsi agregate. Contoh: Untuk menampilkan jumlah buku per kode penerbit. atau bahkan sELecT. tetapi hanya yang jumlahnya >10 saja yang ditampilkan.HAVING < kondisi > Klausa ini digunakan untuk melakukan filtering pada fungsi agregate. LATIHAN SQL SELECT Statement SQL Select sangat puenting luar biasa dalam memanage suatu database. dengan ASC mengurutkan mulai dari terkecil hingga terbesar. maka pengurutan dari hasil sama itu dilakukan pada parameter kolom berikutnya. DESC mengurutkan mulai dari terbesar hingga terkecil. 88 Secangkir Kopi Java . ataupun dalam pembuatan aplikasi. Terserah mana yang kamu suka. Select. Contoh: SELECT * FROM authors ORDER BY lastName. Tips: Berbeda dengan Java. SELECT idPenerbit. huruf besar dan kecil dianggap sama. Order By bisa diikuti parameter lebih dari satu kolom dengan prioritas mulai dari yang paling kiri. COUNT(*) FROM koleksi GROUP BY idPenerbit HAVING COUNT(*)>10 ORDER BY Klausa ini digunakan untuk mengurutkan hasil query berdasarkan kolom tertentu. firstName ASC Ini akan menampilkan seluruh kolom dari tabel authors dan diurutkan berdasarkan kolom lastName dan firstName secara ascending. Jika kolom terkiri sama.

Jumlah seluruh mahasiswa. 2. 15. Daftar Dosen yang tidak memiliki anak wali. Daftar Jadwal perkuliahan (hari. Total IPK per mahasiswa (nrp. Daftar Mahasiswa (nrp. jam. 7. nama). nama. 12. 6. Daftar dosen yang anakwalinya pernah mendapatkan nilai 'E'. alamat) yang namanya sama. 3. Daftar Mahasiswa (nrp. Daftar Mahasiswa (nrp. 4. 14. nama) yang dosen walinya bernama "Irfan Subakti". 8. Java Database Connectivity [ JDBC ] 89 --> rumus IPK = . jeniskel) yang berjenis kelamin lakilaki. Daftar Mahasiswa (nrp. 10. 18. nama. nama. Daftar nama matakuliah beserta nilai hurufnya untuk mahasiswa dg NRP='12020012'. Daftar Mahasiswa (nrp. Daftar Mahasiswa (nrp. nama) SUM(sks*kredit) / SUM(kredit). nama) yang dianggap lulus (tidak pernah mendapatkan nilai "D" atau "E"). 13. alamat) yang beralamat di "Sidoarjo" Daftar Matakuliah (*) beserta semester diajarkan urut berdasarkan semester dan nama. 5. Nilai tertinggi. alamat) dan dosen walinya (nip. 11. 9. nama. nama) beserta nama dosen walinya (nip. Jumlah seluruh mahasiswa per jenis kelamin. Daftar nama mahasiswa dan nilai matakuliah untuk mahasiswa kelas "C1" dan matakuliah "Pemrograman Database". alamat) yang alamatnya sama-sama di "Sidoarjo". 17.Buat query pada database AkademikPIKTI: 1. rata-rata per nama Mata Kuliah. 16. Daftar matakuliah dan mahasiswa yang harus mengikuti ujian susulan matakuliah tsb (nilai <56). nama matakuliah dan dosen pengajar). Daftar mahasiswa (nrp. nama. terendah.

nama like 'Irfan Subati' 06:\> SELECT mhs.kodekul=matakul.jam.nipwali=dosen.nama.jeniskel FROM Mahasiswa WHERE jeniskel='L' 02:\> SELECT nrp.nrp='12020012' and pesertakul.pesertakul WHERE pesertakul.dosen WHERE 90 Secangkir Kopi Java .alamat like '*Sidoarjo*') 07:\> SELECT matakul.alamat FROM mahasisiwa.dosen.dosen.dosen WHERE mahasiswa.jam.namakul.nip 05:\> SELECT mahasiswa.kodesemester FROM matakul.semester WHERE matakul.alamat FROM Mahasiswa WHERE alamat like '*Sidoarjo*" 03:\> SELECT matakul. Jawaban: 01:\> SELECT nrp.mhs.alamat.hari.nip.nip AND dosen.dosen.dosen WHERE (mhs.dosen.semester. rata-rata per kelas dan jeniskelamin. terendah.namakul.mahasiswa.pesertakul.namakul 04:\> SELECT mahasiswa.nrp.alamat like '*Sidoarjo*') AND(dosen. mahasiswa.mhs.nrp.nrp.nama.nilaihuruf FROM mataku.nama FROM Mahasiswa.matakul.nip.nama.nama.nipwali=dosen.nama.namajam. 20.kodesemester ORDER BY matakul. alamat mahasiswa dan dosen yang beralamat di "Sidoarjo" yang urut berdasarkan nama.nama FROM mahasiswa.nipwali=dosen.dosen WHERE mahasiswa.dosen . Gabungan seluruh nama.nip) AND (mhs.kodesemester = semester. Nilai tertinggi.nama FROM sesikuliah.matakul.nama.kodekul 08:\> SELECT hari.namahari..19.doesn.

nrp=pesertakul.kodehari AND sesikuliah.pesertakul.kodejam=jam.nihuruf='E' 13:\> SELECT matakul.pesertakul WHERE mahasiswa.nrp.mahasiswa.kelas='ca' AND matakul.pesertakul.doesn.nama.namakul.nrp=pesertakul.pesertakul.alamat FROM mahasiswa WHERE nama IN(SELECT nama FROM mahasiswa GROUP BY name HAVING COUNT(*) >1) 15:\> SELECT COUNT (*) FROM mahasiswa 16:\> SELECT COUNT (*) FROM mahasiswa GROUP BY jeniskel Java Database Connectivity [ JDBC ] 91 .kodekul AND matakul.nrp=pesertakul.nrp AND pesertakul.nipdosen 09:\> SELECT mhs.mahasiswa.nrp AND pesertakul.kodehari=hari.kodekul=matakul.nilai FROM mahasiswa.kodekul=pesertakul.nama.nilai<56 14:\> SELECT distinct nama.nama FROM mahasiswa.matakul WHERE mhs.kodejam AND sesikuliah.kodekul AND dosen.kodekul=matakul.namakul='Pemrograman Database' 10:\> SELECT * FROM dosen WHERE nip NOT IN (SELECT distinct nipwali from mahasiswa) 11:\> SELECT nrp.nip=sesikuliah.sesikuliah.nipwali=dosen.nama FROM mahasiswa WHERE nrp NOT IN (SELECT distinct nrp FROM pesertakul WHERE (nihuruf='D' OR nihuruh='E')) 12:\> SELECT distinct dosen.nip AND mahasisea.nrp AND pesertakul.nrp FROM dosen.matakul WHERE mahasiswa.kodekul AND pesertakul.

nilai) FROM pesertakul.nama. AVG(pesertakul. Jadi kalau ada sedikit error.pesertakul.maasiswa.alamat like '*Sidoarjo*' UNION ALL SELECT dosen.nilai.kul). Bisa-bisa aku nanti 92 Secangkir Kopi Java . MIN(pesertakul.nilai).jeniskel 20:\> SELECT mahasiswa. aku sudah bilang “sori”.pesertakul WHERE pesertakul.namakul 19:\> SELECT pesertakul.alamat like '*Sidoarjo*' ORDER BY nama Aku perlu mohon maaf bahwa SQL-ku diatas tidak ku uji coba ulang – aku tinggal kopi paste dari My Documents-ku. mahasiswa.nama AS nama.nangka*matakul.SUM(nilai. MIN(pesertakul. mahasiswa.alamat AS alamat FROM mahasiswa WHERE mahasiswa.dosen.17:\> SELECT mahasiswa.nihuruf=nilai.nilai WHERE mahasiswa.s ks)/SUM(matakul.nrp=pesertakul.nrp GROUP BY pesertakul.kelas.nilai).nilai.nrp. ii.alamat FROM dosen WHERE dosen.AVG(pesertakul. Java Database Connectivity First Run! Setelah kita membahas habis SQL dengan begitu detail.nilaikul.kul) FROM matakul.nama. mahasiswa.nilai.kodekul AND pesertakul.jeniskel.kode 18:\> SELECT matakul.kelas.nrp=pesertakul.matakul. MAX(pesertakul.kodekul GROUP BY matakul. MAX(pesertakul. rasanya tidak etis jika aku kembali membahas konsep JDBC.sks) FROM mahasiswa.mahasiswa WHERE mahasiswa.kul).kodekul=matakul.kodekul=matakul.nrp AND pesertakul.

*. salah satu cara Java mengakses database. sebagai perkenalan pertama kita dengan JDBC. mari kita pelototi bagaimana Java mengakses database dengan JDBC.dijuluki ngomong doang. //statement Statement st = con. package galih. //query database ResultSet rsHasil = st.createStatement().printStackTrace(). Karena itu.swing. //connect to database Connection con = DriverManager. public class QueryToDatabase extends JFrame { private StringBuffer hasil.odbc. try { prepareQuery().JdbcOdbcDriver" ).jdbc.sql.1 – First run kita terhadap database Akademik. } catch ( Exception e ) { e. //konstruktor public QueryToDatabase() { super ( "JDBC . Ini untuk sekedar mengetahui.*. Kita menggunakan Open Database Connectivity. Java Database Connectivity [ JDBC ] 93 .*.jdbc.getConnection( "jdbc:odbc:Akademik" ). import javax. import java. createGUI(). import java.awt.forName( "sun.executeQuery( Listing 3. } } //connect to database private void prepareQuery() throws Exception { //loading driver class Class.First Sight!" ). untuk lebih teknisnya kita bahas setelah ini.

"SELECT * FROM dosen" );

//processing hasil = new StringBuffer(); ResultSetMetaData metaData = rsHasil.getMetaData(); int numCol = metaData.getColumnCount();

//kolom, result set mulai dari 1, array dari 0 for ( int i = 1; i <= numCol; i++ ) { hasil.append( metaData.getColumnName( i ) + "\t" ); } hasil.append( "\n" );

while ( rsHasil.next() ) { for ( int i = 1; i <= numCol; i ++ ) { hasil.append( rsHasil.getString( i ) + "\t" ); } hasil.append( "\n" ); }

//close st.close(); con.close(); }

private void createGUI() { JTextArea txtHasil = new JTextArea ( hasil.toString() ); Container contPane = getContentPane(); contPane.add( new JScrollPane ( txtHasil ), BorderLayout.CENTER ); setDefaultCloseOperation ( EXIT_ON_CLOSE ); setSize ( 400, 350 ); setVisible ( true ); }
Listing 3.1 – First run kita terhadap database Akademik. Kita menggunakan Open Database Connectivity, salah satu cara Java mengakses database.

94

Secangkir Kopi Java

//kode sakti! public static void main ( String[] args ) { new QueryToDatabase(); } }
Listing 3.1 – First run kita terhadap database Akademik. Kita menggunakan Open Database Connectivity, salah satu cara Java mengakses database.

Dalam menulis program yang membutuhkan query ke database, yang perlu kita lakukan adalah hal-hal sbb: 1. Menentukan driver dari database. Kita akan bahas lebih mendetail nanti. 2. Membuat ditentukan. 3. 4. Dari koneksi tersebut kita membuat statement. Dari statement tersebut kita melakukan query ke database. Query bisa berbentuk SQL ( Structured Query Language ), DDL ( Data Definition Language ), ataupun DML ( Data Manipulation Language ). koneksi pada database yang alamatnya telah

Method prepareQuery() pada listing 3.1 di atas melakukan query ke database. Method ini meng-throw 2 eksepsi yaitu SQLException dan
ClassNotFoundException.

Kita

menyingkatnya

dengan

melemparkan induk dari dua eksepsi ini, yaitu Exception. Method
Class.forName ( String classDriver )

menentukan class yang digunakan sebagai driver dari database. Class ini harus berada di dalam CLASSPATH. Di sini kita memakai driver JDBCODBC yang telah built-in di dalam library JVM ( Java Virtual Machine ). Kita melakukan koneksi dengan method

DriverManager.getConnection ( String address ) yang mereturn

sebuah object Connection. String

address

adalah alamat letak

Java Database Connectivity [ JDBC ]

95

database

berada.

Tata

nama

untuk

alamat

ini

adalah

“jdbc:<driver>:<database>”.

Dari koneksi tersebut kita membuat statement query dengan method
createStatement().

Kemudian

kita

eksekusi

dengan

executeQuery ( String query ) yang akan menghasilkan sebuah ResultSet. ResultSet kita proses untuk kita tampilkan pada text area. Kita

mendapatkan

nama-nama

kolom

(

field

)

dengan

method

getMetaData(). ResultSetMetaData merupakan ResultSet khusus

yang mengurusi semua atribut dari ResultSet seperti nama kolom, jumlah kolom, dsb.

Gambar 3.1 – Tampilan hasil query yang kita tampilkan pada sebuah JTextArea.

Driver JDBC Koneksi ke database adalah tanggung jawab dari driver. Java 2 SDK hanya memiliki satu driver built-in yaitu tipe driver JDBC-ODBC. Untuk melakukan koneksi dengan tipe lain, kita membutuhkan driver spesifik yang harus diletakkan pada CLASSPATH.

96

Secangkir Kopi Java

Driver JDBC di-load dengan method Class.forName ( String driver ). Contoh: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Class.forName("postgresql.Driver"); Class.forName("oracle.jdbc.driver.OracleDriver"); Driver JDBC dapat mengerti alamat database yang ditulis dalam URL ( Uniform Resource Locator ). Berikut ini adalah tata nama alamat database untuk beberapa database. Setiap alamat database dengan koneksi JDBC-ODBC memiliki format berikut:
“jdbc:odbc:<dns>” <dns> adalah Data Source Name yang digunakan pada ODBC. Dalam

Listing 3.1 DNS yang dipakai adalah Akademik, sehingga alamatnya menjadi “jdbc:odbc:Akademik” Untuk database Oracle, contoh alamat database yang berada pada mesin Eliza dengan nama database Coba adalah:
String url = "jdbc:oracle:thin:user/password@( description=(address_list=( address=(protocol=tcp) host=Eliza ) (port=1521))) (source_route=yes) (connect_data=(sid=Coba)))";

Untuk MySQL, tata nama alamatnya beda lagi. Berikut ini adalah contoh alamat database dengan nama Coba, dengan nama user fatso dan password ganteng.
String url = “jdbc:mysql://localhost/Coba?user=fatso;password=ganteng”;

Tipe Driver JDBC ada empat macam, yaitu JDBC-to-ODBC Bridge Driver, Native-API, JDBC-Net Pure Java Driver, dan Native Protocol Pure Java Driver.

Java Database Connectivity [ JDBC ]

97

Koneksi Database Koneksi ke database dapat didapat dengan memanggil method DriverManager. String user. termasuk MS-ACCESS. dengan perintah yang tidak database-specific. Konfigurasi ini sama dengan 4 No. Native-Protocol Pure Java. artinya apapun query kita dengan menggunakan koneksi ini. Secara default. 1 Konfigurasi ini mengharuskan ODBC terinstall pada komputer client. JDBC membuat koneksi dengan Microsoft ODBC (Open Database Connectivity). URL yang dimaksud telah kita bahas tadi dengan tatanamanya dengan cukup njlimet. String password ). JDBC-Net Pure Java.getConnection( String url ) atau DriverManager. Pemanggilan method di atas akan mereturn objek Connection. tidak semua vendor database membuat driver spesifik untuk Java. kelemahannya. Terkenal sebagai konfigurasi paling lambat. konfigurasi ini adalah yang tercepat.3 hanya saja menggunakan network protocol yang database-specific. Konfigurasi ini berkomunikasi dengan 2 3 database lewat network protocol. hasilnya mempengaruhi langsung kondisi database. Kita dapat mengubah setting ini dengan method 98 Secangkir Kopi Java . koneksi ini bersifat auto commit.Tipe Penjelasan JDBC-to-ODBC Bridge Driver. Native-API. Konfigurasi ini dapat melakukan koneksi secara langsung ke database karena langsung memanggil method yang ada di driver lewat JNI (Java Native Interface). Server akan menerjemahkan request ini sebagai request database-specific.getConnection ( String url.

executeQuery ( String query ). Update Statement. Update Statement Statement ini biasanya dipakai untuk Data Definition Language ( DDL ) ataupun Data Manipulation Language ( DML ) seperti INSERT INTO. Dua method ini menghasilkan objek ResultSet dari query yang kita lakukan. Nilai 0 akan didapat jika method executeUpdate tidak berjalan dengan sukses. maka query yang kita lakukan tidak mempengaruhi database sebelum kita memanggil method commit().setAutoCommit ( boolean condition ). yaitu Query Statement. kita dapat membuat statement untuk melakukan query ke database.createStatement(). Java Database Connectivity [ JDBC ] 99 . dsb. Pada akhirnya Update Statement memanggil method Statement.executeUpdate ( String updateString ) yang mereturn nilai integer. int resultSetConcurrency ). ResultSet result = st. dan Prepared Statement. Statement SQL dimasukkan dalam objek Statement ketika kita memanggil method Statement. Query Statement Aku biasa menggunakan dua method createStatement untuk membuat statement SQL. UPDATE. Statement Setelah koneksi kita dapat. Kita dapat menghasilkan objek ResultSet dengan memanggil method Statement. Ada beberapa macam statement yang sering digunakan. Mereka adalah: createStatement() createStatement ( int resultSetType.executeQuery ( “SELECT * FROM mahasiswa” ).executeXXX. Contoh: Statement st = con. Method createStatement() menghasilkan result set dengan tipe TYPE_FORWARD_ONLY dan konkurensi CONCUR_READ_ONLY. Ini akan kita bahas segera. Jika nilainya false.

PreparedStatement merupakan semacam template yang dapat kita gunakan berkali-kali. setInt. thread JVM.Contoh: String query = “INSERT INTO mahasiswa ( nama ) VALUES ( ‘Galih’ )” int code = st. setXXX tergantung tipe apa yang dimasukkan. //bisa dari text field String umur = getUserInput(). i++ ) { String nama = getUserInput(). Garbage Collector juga menyebabkan Java tidak memerlukan sebuah destructor. int hasil = st. Ini membebaskan programmer dari tugas manajemen memori manual yang memusingkan.executeUpdate( query ). '" + umur + "' )".executeUpdate ( query ). Kita bisa melakukannya dengan cara seperti pseudo-code di bawah ini: for ( int i = 1. Objek String tidak dapat diperbarui. Prepared Statement Terkadang kita melakukan query berkali-kali dengan query yang sama dengan parameter yang berbeda. Misalkan kita ingin memasukkan 10 data baru ke dalam sebuah tabel. i <= 10. Template ditandai dengan karakter ‘?’ yang diisi dengan method setXXX. Oleh karena itu metode ini kurang efektif. ataupun setDouble. meskipun di variabel yang sama. } Dapat kau lihat bahwa kita membuat objek String query sebanyak 10 kali. Java memiliki cara yang lebih baik dengan menggunakan PreparedStatement. Referensi lama dari variabel String akan dikumpulkan oleh garbage collector1. Contoh: 1 Garbage Collector merupakan thread berprioritas rendah yang bertugas me-reclaim memori yang tidak digunakan. umur ) VALUES( '" + nama + "'. bisa setString. 100 Secangkir Kopi Java . String query = "INSERT INTO user( nama.

dan semacamnya. } con2. st4.last(). Java Database Connectivity [ JDBC ] 101 . prsnl_no )" + " VALUES ( ?. ? )".setString( 2. ?.setString( 1. Kita mendapatkan nilai dari suatu baris dan kolom dengan menggunakan method getXXX ( int noKolom ) atau getXXX ( String namaKolom ). rsReviewer.prepareStatement( query4 ).getRow().rollback().first(). PreparedStatement st4 = con2. ResultSet Hasil query dari method Statement. if ( result2 == 0 ) { con2.String query = "INSERT INTO paper_reviewer ( paper_no. kd_kode.getString( "prsnl_no" ). XXX merupakan tipe data sepeti Int. st4. st4.executeQuery ( String query ) menghasilkan objek ResultSet. int result2 = st4.executeUpdate(). return false. } } while ( rsReviewer. String. int rowCount = rsReviewer. noReviewer ). noPaper ).next() ). "2" ). if ( rowCount >= 1 ) { do { String noReviewer = rsReviewer. ResultSet adalah representasi dari tabel yang dapat kita gunakan untuk bernavigasi antar baris di tabel.commit().setString( 3. Potongan program di atas memasukkan data berkali-kali sepanjang objek ResultSet rsReviewer dengan template PreparedStatement. Object. rsReviewer.

jika tidak. Kamu harus melakukan query lagi untuk melihat perubahan yang terjadi. dan perubahan pada database direfleksikan pada result set. dan TYPE_SCROLL_SENSITIVE.ResultSet memiliki kursor pada baris tabel hasil query yang dapat digerakkan. Kursor dapat bergerak maju mundur. TYPE_FORWARD_ONLY TYPE_SCROLL_INSENSITIVE TYPE_SCROLL_SENSITIVE Interface ResultSet juga memiliki tipe updating yaitu CONCUR_READ_ONLY dan CONCUR_UPDATABLE. Type Scrolling Kursor ResultSet Type Penjelasan Kursor hanya dapat bergerak maju. kamu harus mengetahui bahwa database yang bersangkutan harus mendukung result set updatable. program akan terlempar ke kondisi eksepsi. Type Konkurensi ResultSet Type Penjelasan ResultSet tidak dapat meng-update CONCUR_READ_ONLY database meskipun dengan pemanggilan method update(). Ada beberapa macam tipe scrolling. Kursor dapat bergerak maju mundur.createStatement(). TYPE_SCROLL_INSENSITIVE. mblejog ke depan atau belakang. Method ResultSet yang dapat dipanggil hanyalah next(). aku memakai yang read only. Untuk memakai updatable. Merupakan tipe default dari method Connection. ResultSet dapat meng-update CONCUR_UPDATABLE database. Biasanya. Perubahan yang terjadi pada database tidak direfleksikan ke result set. yaitu TYPE_FORWARD_ONLY. 102 Secangkir Kopi Java .

Oce. Aku tetap akan menggunakan ODBC. tidak mau menggerakkan jarimu yang malas itu di atas keyboard. : Menempatkan kursor pada posisi terakhir. Navigasi ResultSet ResultSet yang dapat bergerak ke sana ke mari dapat kita gerakkan dengan perintah sederhana. relative(1) menggerakkan kursor satu baris ke depan. first() last() afterLast() : Menempatkan kursor pada baris pertama. Berikut method untuk navigasi kursor ResultSet: beforeFirst() : Posisi default. 103 Java Database Connectivity [ JDBC ] . : Menempatkan kursor pada sebelum baris terakhir. Secara default. relative(pos) : Menempatkan kursor pada baris ke-pos relatif dari posisi kursor sekarang. percuma aku ngomong JDBC sampai berbusa-busa kalau kamu cuma bengong baca ini. Menempatkan posisi kursor pada sebelum baris pertama. oleh karena itu set dulu ODBC-mu sebelum menulis program berikut. absolute(1) merupakan baris pertama dan absolute(-1) merupakan baris terakhir. absolute(pos) : Menempatkan kursor pada baris ke-pos.supportsResultSetConcurrency() mereturn nilai boolean.Kamu dapat mengetahui apakah database mendukung result set updatable atau tidak dengan memanggil method yang Connection. kursor diletakkan pada sebelum baris pertama tabel. teori dasar-dasar JDBC sudah kita bahas tuntas. Tapi apalah arti teori tanpa praktik? Seperti halnya kamu.getMetaData(). next() previous() : Menempatkan kursor satu baris ke bawah / depan. : Menempatkan kursor satu baris ke atas / belakang. Sekarang mari kita membuat sebuah user interface untuk melakukan query sederhana ke database. Pemanggilan method next() akan membuat kursor terletak pada baris pertama.

ResultSet. private Statement statement. String url. import javax.package galih.getConnection( url ). //konstruktor public ResultSetTableModel( String driver.util.table.2 – ResultSetTableModel merupakan model dari JTable yang digunakan untuk merepresentasikan objek ResultSet menjadi sesuatu yang nyata.TYPE_SCROLL_INSENSITIVE. import java. ClassNotFoundException { //driver database Class. } //get column class public Class getColoumnClass( int column ) { try { String className = metaData.sql.*. //dapatkan koneksi ke database con = DriverManager.getColumnClassName( column + 1 ).forName( driver ). public ResultSet resultSet. //buat statement statement = con.CONCUR_READ_ONLY ). String query ) throws SQLException. Listing 3. ☺ 104 Secangkir Kopi Java . import java.swing. //PENTING!! Index ResultSet dimulai dari 1 dan JTable mulai //dari 0 public class ResultSetTableModel extends AbstractTableModel { private Connection con. private int numberOfRows. //execute query setQuery( query ).*.*. private ResultSetMetaData metaData.jdbc.createStatement( ResultSet.

} Listing 3.getColumnName( column + 1 ). return fullName. } catch ( Exception e ) { e. } //get jumlah kolom public int getColumnCount() { try { return metaData. } //get nama kolom public String getColumnName( int column ) { try { //jtable mulai 0.printStackTrace().indexOf( "_" ) ). } return 0. } catch ( SQLException e ) { e. result set 1 String fullName = metaData. } //get jumlah baris public int getRowCount() { return numberOfRows.class.2 – ResultSetTableModel merupakan model dari JTable yang digunakan untuk merepresentasikan objek ResultSet menjadi sesuatu yang nyata.return Class. } catch ( SQLException e ) { e.getColumnCount().substring( fullName. } return "".printStackTrace(). } return Object.toLowerCase().printStackTrace(). ☺ Java Database Connectivity [ JDBC ] 105 .forName( className ).

public Object getValueAt( int row. } } } Listing 3.close().2 – ResultSetTableModel merupakan model dari JTable yang digunakan untuk merepresentasikan objek ResultSet menjadi sesuatu yang nyata. } //execute query public void setQuery( String query ) throws SQLException { resultSet = statement. con. int column ) { try { //gerakkan kursor resultSet. Data yang kita ambil dari database 106 Secangkir Kopi Java .getMetaData(). } //finalizing protected void finalize() { try { statement.getRow(). } return "".last(). fireTableStructureChanged(). } catch ( SQLException e ) { e. ☺ Kita akan menggunakan ilmu yang telah kita dapat di bab 2 untuk kita gunakan di “dunia nyata”. numberOfRows = resultSet. //number of rows resultSet. return resultSet.close().printStackTrace().executeQuery( query ).printStackTrace().getObject( column + 1 ).absolute( row + 1 ). } catch (SQLException e) { e. metaData = resultSet.

kemudian memanggil method setQuery ( String query ) untuk melakukan query default.getMetaData() yang mereturn objek ResultSetMetaData. dan JTable mulai dari 0. Pada method getValueAt ( int row.kita masukkan pada sebuah table model yang nantinya digunakan JTable sebagai modelnya. Jika gagal mengidentifikasi class dari suatu kolom. Harus ditambah 1 karena terjadi perbedaan permulaan index dari ResultSet dan JTable.getColumnCount(). diasumsikan bahwa class tersebut adalah class dari Object.executeQuery ( String query ). Yang perlu diperhatikan betul bahwa index dari ResultSet mulai dari 1. membuat koneksi. Method getColumnClass ( int column ) mendapatkan class dari kolom yang ada di ResultSet. Konstruktor pada Listing 3. Setelah itu kita perlu memanggil fireTableStructureChanged() untuk memberitahu JTable bahwa data model telah berubah total sehingga JTable menyesuaikan view-nya. dan membuat statement.2 akan melakukan inisialisasi awal dengan menentukan driver. int column ). Di sini kita mengembalikan jumlah baris yang dimiliki ResultSet dengan mereturn ResultSetMetaData. maka kita akali dengan menempatkan kursor di last() dan mendapatkan nomor barisnya dengan method getRow(). ResultSet tidak memiliki cara langsung untuk mendapatkan jumlah baris. Hal sama pada method getColumnName ( int column ). Java Database Connectivity [ JDBC ] 107 . JTable mendapatkan jumlah baris melalui method getColumnCount(). Kemudian kita dapatkan atribut dari hasil query dengan memanggil method ResultSet. kita gerakkan kursor satu ke bawah dari row. Method setQuery ( String query ) akan melakukan query dengan memanggil method Statement. Di sini kita juga menggunakan meta data untuk mendapatkan nama kolom dari kolom tertentu. kemudian kita returnkan Object pada column + 1.

import java.*. import java. import javax. url. private JButton btnSubmit.odbc.event. import java.awt.3 – QueryResult menampilkan hasil query yang kita masukkan pada text area dalam sebuah tabel. private JTextArea queryArea. try { initialize().printStackTrace().*. } catch ( Exception e ) { e. Listing 3.exit( 1 ). //url String url = "jdbc:odbc:Akademik".awt. private JTable table. //tampilkan ke tabel tableModel = new ResultSetTableModel( driver.swing.JdbcOdbcDriver".*.jdbc. setEventHandler().jdbc. //default query String query = "SELECT * FROM mahasiswa". 108 Secangkir Kopi Java .package galih. public class QueryResult extends JFrame { //instans private ResultSetTableModel tableModel. //konstruktor public QueryResult() { super( "Query ke Database" ).*.sql. } } private void initialize() throws Exception { //driver String driver = "sun. query ). System.

add( new JScrollPane( table ).addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { //new query try { tableModel. cp.setWrapStyleWord( true ). 100 ).toString().CENTER ). 3. BorderLayout. } catch ( SQLException ex ) { String exception = ex.setQuery( queryArea. btnSubmit. //pasang pada container Box box = Box. box. //button btnSubmit = new JButton( "Submit" ). setSize( 500. Java Database Connectivity [ JDBC ] 109 . box.getText() ).add( btnSubmit ). queryArea.add( new JScrollPane( queryArea ) ). } private void setEventHandler() { btnSubmit. getRootPane().setMnemonic( 'S' ).table = new JTable( tableModel ).setLineWrap( true ). BorderLayout. cp. setDefaultCloseOperation( EXIT_ON_CLOSE ).createHorizontalBox().NORTH ).add( box.3 – QueryResult menampilkan hasil query yang kita masukkan pada text area dalam sebuah tabel. Listing 3. Container cp = getContentPane().setDefaultButton( btnSubmit ). queryArea. //query area queryArea = new JTextArea( query. setVisible( true ). 400 ).

Yang dilakukan di sini cukup sederhana. dan query default yang dikirimkan ke ResultSetTableModel untuk diproses menjadi sebuah table model.showMessageDialog( QueryResult. Oce. exception.3 – QueryResult menampilkan hasil query yang kita masukkan pada text area dalam sebuah tabel. } //pablik setatik void ma-in public static void main( String[] args ) { new QueryResult(). Udah. class pada listing 3. Method setEventHandler() akan melakukan pemasangan event pada button Submit ketika di-klik. url database.2 – Hasil query yang ditampilkan pada JTable dengan menggunakan ResultSetTableModel 110 Secangkir Kopi Java .this. "\n") ).JOptionPane.3 adalah class yang menampilkan hasil query yang kita masukkan pada text area. Method initialize() akan melakukan inisialisasi awal dari driver. gitu thok. Dari table model tersebut kita bangun JTree. yaitu mengambil String yang ada pada queryArea dan mengirimkannya ke method ResultSetTableModel. Gambar 3. } } Listing 3. } } }).setQuery ( String query ) untuk dieksekusi.replaceAll( " ".

studi kasus jdbc – address book .

.

Gambar 4. pembuatan tabel dengan DDL. saat menikmatinya. Relasi yang digambarkan dengan cara di atas disebut Relasi Cakar Ayam. Studi Kasus JDBC – Adress Book 113 . Di sini aku akan menggunakan database MySQL dan driver yang kugunakan bukan JDBC-ODBC-Bridge lagi tetapi Native API. hingga penulisan program dan terakhir. Buku alamat sangat tepat untuk dijadikan studi kasus karena tidak terlalu rumit dan dapat mencangkup semua teori dasar JDBC. Database Design Untuk database besar hingga lebih dari 10 tabel dengan relasi yang rumit.Kali ini kita akan mengimplementasikan semua teori-teori tentang JDBC ke dalam sebuah aplikasi buku alamat. i. biasanya aku memakai Sybase Power Designer 9 untuk mendesainnya. aku tidak membahas itu. Tetapi sekali lagi karena ini bukan buku tentang database.1 – Relasi antar entitas pada database address book. instalasi database. Aku akan memulainya dari mendesain database.

Kemudian.23.53 for Windows NT. Instalasi Database dan Pembuatan Database Aku memakai database MySQL ver.ii. di kompieku keluar seperti ini: 114 Secangkir Kopi Java . server MySQL otomatis akan jalan sendiri. DBMS ini dapat kamu dapatkan secara gruatis tanpa harus mbajak di http://mysql. jalankan client dengan perintah: F:\mysql\bin> mysql Jika sukses. Commands end with .exe dan ikuti petunjuk yang muncul. Type ‘\c’ to clear the mysql> _ Kita akan membuat database buku_alamat dengan perintah: mysql> create database buku_alamat. sehingga setiap kompie dijalankan. Your MySQL connection id is 2 to server version: 3.’ buffer. 1 row affected (0. or ‘\h’ for help. setelah instalasi selesai. kamu akan disambut dengan kata-kata seperti F:\mysql\bin> mysql Welcome to the MySQL monitor. buka command prompt dan pindah direktori ke [my_sql_home]/bin.com.06 sec) Untuk melihat apakah database itu benar-benar ada.23. or \g.exe agar menjadi service. 3. Setelah mendapatkan paket installernya. Di kompieku terletak di F:\mysql\bin. kita bisa memakai perintah: mysql> show databases. jalankan setup. Jalankan server dengan mengetik di command prompt: F:\mysql\bin> mysqld-max-nt Atau kamu bisa menjalankan winmysqladmin. Setelah server berjalan. Query OK.53max-nt Type ‘help.

mysql> show databases. Oce. not null. +-------------------------+ | Database | +-------------------------+ | buku_alamat | | fatso | | galihsatria_uk_db | | mysql | | test | +-------------------------+ 5 rows in set (0. null. Database changed mysql> _ Sekarang kita siap membuat tabel. Studi Kasus JDBC – Adress Book 115 . null. not null. Tabel Orang: create table if not exists ORANG ( ORANG_ID int NAMA varchar(30) FOTO longblob. primary key (ALAMAT_ID) ). DESA varchar(50) KECAMATAN varchar(50) KABUPATEN varchar(50) PROVINSI varchar(50) NEGARA varchar(40) KODEPOS varchar(10). kita harus memilih dulu database mana yang akan kita gunakan.01 sec) mysql> _ Sebelum kita membuat tabel dengan DDL. primary key (ORANG_ID) ). not null. mari kita buat satu per satu: Tabel Alamat: create table if not exists ALAMAT ( ALAMAT_ID int JALAN varchar(50). not not not not not null. null. maka kita tulis: mysql> use buku_alamat. null. Karena kita akan menggunakan database buku_alamat.

primary key (ORANG_ID. EMAIL_ID int not null. ALAMAT_ID) ). RUMAH varchar(15). Index Constraint pada tabel Orang_Alamat dengan Orang untuk “Orang Memiliki Alamat”: create index MEMILIKI_FK on ORANG_ALAMAT ( ALAMAT_ID ). Index Constraint pada tabel Orang_Alamat dengan Orang untuk “Alamat Dimiliki Orang”: create index DIMILIKI_FK on ORANG_ALAMAT ( ORANG_ID ). MOBILE varchar(20). TELP_ID int not null. Index Constraint pada tabel Orang dengan Telp: create index ORANG_TELP_FK on TELP ( ORANG_ID 116 Secangkir Kopi Java . primary key (ORANG_ID. ALAMAT_ID int not null. primary key (ORANG_ID. TELP_ID) ).Tabel Orang_Alamat ( Tabel perantara relasi many-to-many ): create table if not exists ORANG_ALAMAT ( ORANG_ID int not null. EMAIL_ADDRESS varchar(50). Tabel Email: create table if not exists EMAIL ( ORANG_ID int not null. EMAIL_ID) ). Tabel Telp: create table if not exists TELP ( ORANG_ID int not null.

). user interface. Kamu bisa mencek masing-masing tabel dengan perintah DESCRIBE tabel. sekarang kita memulai hal yang menyenangkan: menulis kode programnya! iii. Index Constraint pada tabel Orang dengan Email: create index ORANG_EMAIL_FK on EMAIL ( ORANG_ID ). Studi Kasus JDBC – Adress Book 117 . atau koneksi ke database.12 sec) mysql> _ Sayang sekali MySQL versi 3 belum mendukung foreign key constraints. Class AddressEntry Class ini adalah sebuah java bean yang bertugas mengenkapsulasi entri data tiap record. +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | ORANG_ID | int(11) | | PRI | 0 | | | NAMA | varchar(30) | | | | | | FOTO | longblob | YES | | NULL | | +----------+-------------+------+-----+---------+-------+ 3 rows in set (0. Dengan program yang terpisah secara jelas. misalnya: mysql> describe orang. di Java aku sangat juaraaang melakukan debugging ). Penulisan Kode Program dengan Java Program yang akan kita buat hanya dapat melakukan insert table dan select saja. Aku sengaja tidak memasukkan fiture update dan searching agar programnya tidak terlalu panjang. Java Bean sangat diperlukan di sini untuk memisahkan mana yang data. jadi kita harus amat hati-hati dalam manajemen datanya. Nah. mudah bagi kita untuk membaca ataupun mendebugnya ( tapi jujur.

} public Vector getJalan() { return jalan. } //getters public Vector getDesa() { return desa. } public String getFotoPath() { return fotoPath.//java-bean untuk entry address book package addressbook.orangID = id.util. } public Vector getKec() { return kec. } public Vector getEmail() { return email. telp = new Vector().1 – Java Bean yang merepresentasikan entri data. prov = new Vector(). //konstruktor public AddressEntry() { this( 0 ). import java. public public public public public public public public public Vector Vector Vector Vector Vector Vector Vector Vector Vector jalan = new Vector(). } public AddressEntry( int id ) { this. email = new Vector(). kec = new Vector(). negara = new Vector(). kodepos = new Vector(). desa = new Vector(). public String fotoPath = "". public String nama = "".*. 118 Secangkir Kopi Java . kab = new Vector(). } Listing 4. } public Vector getKab() { return kab. public class AddressEntry { //instans public int orangID.

add( newJalan ). } //add ke vector public void addJalan( Object newJalan ) { jalan.fotoPath = fotoPath.add( newKecamatan ). } public void setNama( String nama ) { this. } public String getNama() { return nama.orangID = orangID. } public Vector getTelp() { return telp. } public Vector getProv() { return prov.nama = nama.public Vector getKodepos() { return kodepos. } public void addKec( Object newKecamatan ) { kec. } public int getOrangID() { return orangID.add( newKab ). } public void setOrangID( int orangID ) { this. } public void addKab( Object newKab ) { kab. } public Vector getNegara() { return negara. } //setters public void setFotoPath( String fotoPath ) { this.1 – Java Bean yang merepresentasikan entri data. } Listing 4. Studi Kasus JDBC – Adress Book 119 .add( newDesa ). } public void addDesa( Object newDesa ) { desa.

add( newKodepos ). dan telp yang setiap satu orang bisa memiliki lebih dari satu. } public void addTelp( Object newTelp ) { telp. } } Listing 4. add fungsinya sama dengan setter. Java Bean tidak melakukan apa-apa. } public void addKodepos( Object newKodepos ) { kodepos. 120 Secangkir Kopi Java .add( newEmail ).add( newProv ). kita nanti akan menyimpannya dalam bentuk byte ( long blob ).clear(). Bean di atas memiliki instance yang kita perlukan untuk mengolah data.clear(). setter untuk men-set nilai ke suatu instance.clear(). ).1 – Java Bean yang merepresentasikan entri data.clear().add( newNegara ). email.add( newTelp ). Tidak praktis bila kita membawa-bawa byte itu dalam bean. Untuk foto. Maka dari itu ia memiliki getter untuk mengambil nilai dari suatu instance. prov. } public void addEmail( Object newEmail ) { email.clear(). telp. dia hanya sebagai perantara. kodepos. misalnya antara koneksi database dengan user interface. desa. Method addXXX ( Object data ) digunakan sebagai setter yang memiliki multiple value seperti alamat ( jalan. kab. dll. negara.clear(). } //clear element's object public void clearAll() { jalan. } public void addNegara( Object newNegara ) { negara.public void addProv( Object newProv ) { prov. dan method clearAll() yang membersihkan nilai dari suatu instance menjadi kosong untuk diisi nilai baru. kec.clear().clear(). email.clear(). desa.

public int next() throws SQLException. package addressbook.sql. Ketika telah “tiba” pada objek yang memerlukan byte-nya. Method yang didefinisikan di sini tidak tergantung kepada database yang digunakan. public int prev() throws SQLException. Listing 4. //initializing result set untuk view public void initView(). //insert into database public int saveToDatabase( AddressEntry entry ) throws SQLException. ke bentuk bytenya.2 – Interface DataAccess mendefinisikan method untuk mengakses database Studi Kasus JDBC – Adress Book 121 . import java. String table ). Lain lagi ceritanya kalau object antara user interface dengan object koneksi database berada pada mesin yang berbeda. kita konversikan path tsb. public interface DataAccess { //trigger public int getLastID( String column. //close connection public void close(). Interface DataAccess Interface DataAccess kita perlukan untuk melakukan akses ke database.maka yang kita simpan adalah pathnya. Foto di dalam bean harus sudah dalam bentuk byte.*. //navigasi result set public void first() throws SQLException. Adanya interface ini membuat struktur program lebih jelas lagi. Interface ini mendefinisikan method-method apa saja yang kita perlukan dalam mengakses database.

//foto public java.Image untuk ditampilkan dalam user interface. //fetch data public AddressEntry fetchData() throws SQLException. Sedangkan untuk mengambil keseluruhan data dari database memakai method fetchData() yang mereturn objek AddressEntry.public void last() throws SQLException. sedangkan format Bitmap ( bmp ) tidak didukung. Method saveToDatabase menyimpan semua entry data ke dalam tabel-tabel sesuai dengan struktur database dan constraint-nya. ketika kupakai objek ini hanya bisa menerima gambar berformat JPG. Method close menutup koneksi dengan database. dan PNG. Method getFoto mengambil foto dalam bentuk objek java. Method-method di luar method yang didefinisikan oleh DataAccess merupakan method yang dibutuhkan secara internal oleh class MySQLAccess. Untuk navigasi antar kontak/record memakai method first. bean pada listing 4. next. } Listing 4.Image getImage(). method initView menginisialisasi hal yang diperlukan untuk melihat isi database.1. Di sini aku tidak memakai tipe data AUTO_INCREMENT karena sulit mengatur constraint-nya. 122 Secangkir Kopi Java . GIF. Sayang sekali. Method ini juga merupakan desain yang kurang baik karena tergantung kondisi database yang seharusnya tidak terjadi dalam interface DataAccess. dan last. prev.awt.2 – Interface DataAccess mendefinisikan method untuk mengakses database Method getLastID merupakan trigger untuk mendapatkan auto_number. Class MySQLAccess Class ini merupakan implementasi dari interface DataAccess untuk mengakses database MySQL.awt.

//prepare select statement sqlSelectAlamat = con. nama. private PreparedStatement sqlSelectTelp.*. telp_id. private PreparedStatement sqlSelectAlamat. foto) VALUES (?. alamat " + "WHERE orang.awt. orang_alamat. private PreparedStatement sqlInsertEmail.sql.alamat_id) VALUES (?. import java. Listing 4. private PreparedStatement sqlInsertTelp." + "kecamatan.alamat_id " + "AND orang.?.?.prepareStatement( "INSERT INTO telp (orang_id. " + "email_address) VALUES (?.?.prepareStatement( "SELECT jalan. import java. negara.?.prepareStatement( "INSERT INTO orang (orang_id.?)" ). private PreparedStatement sqlInsertOrang.?)" ). negara. private PreparedStatement sqlInsertAlamat.prepareStatement( "INSERT INTO orang_alamat (orang_id. public class MySQLAccess implements DataAccess { //instance private Connection con.rumah) " + "VALUES (?. " + "kodepos) VALUES (?. desa. Studi Kasus JDBC – Adress Book 123 . //siapkan sql sqlInsertOrang = con.*. provinsi.*.alamat_id = " + "alamat. import java. " + "provinsi.?)" ).package addressbook.?.?.?.prepareStatement( "INSERT INTO alamat (alamat_id.orang_id = " + "orang_alamat.3 – Class MySQLAccess mengimplementasikan interface DataAccess untuk koneksi ke database dan melakukan interaksi dengan database. private PreparedStatement sqlSelectEmail. kodepos " + "FROM orang. sqlInsertTelp = con. //konstruktor public MySQLAccess() throws Exception { connect(). sqlInsertAlamat = con. desa. sqlInsertOrangAlamat = con.email_id. jalan.?.orang_id = ? " ). private PreparedStatement sqlInsertOrangAlamat.?)" ). kabupaten. private ResultSet rsOrang.?.prepareStatement( "INSERT INTO email (orang_id.orang_id "+ "AND orang_alamat.?)" ).io. kabupaten. kecamatan. sqlInsertEmail = con.

createStatement(). try { String query = "SELECT MAX(" + column + ") FROM " + table.orang_id = ? " ). } //dapatkan byte dari foto untuk disimpan //sebagai tipe BLOB private FileInputStream getFileStream( File file ) { FileInputStream fileStream = null. } catch ( Exception e ) { e.mysql.executeQuery( query ).prepareStatement( "SELECT rumah FROM orang. Statement st = con. try { Class. //telp sqlSelectTelp = con.jdbc.forName( driver ).0. } catch ( SQLException e ) { e. } //akhir konstruktor //connect private void connect() { String driver = "com. ResultSet rsID = st. 124 Secangkir Kopi Java . if ( rsID.printStackTrace().0.next() ) lastID = rsID.orang_id AND " + "orang. String url = "jdbc:mysql://127.telp " + "WHERE orang. con. } Listing 4.Driver". try { fileStream = new FileInputStream( file ). } catch ( IOException e ) { return null.orang_id AND " + "orang.getInt( 1 ). } } //generate auto number public int getLastID( String column.//imel sqlSelectEmail = con.orang_id = email.orang_id = telp. con = DriverManager.setAutoCommit( false ).getConnection( url ). String table ) { int lastID = 0.printStackTrace().3 – Class MySQLAccess mengimplementasikan interface DataAccess untuk koneksi ke database dan melakukan interaksi dengan database. } return lastID.email " + "WHERE orang.1/buku_alamat".orang_id = ? " ).prepareStatement( "SELECT email_address FROM orang.

sqlInsertOrang. ( String ) entry.rollback().setInt( 1. ( int ) file. fis.kodepos.desa. i < entry. i++ ) { sqlInsertAlamat.get( i ) ).size().get( i ) ).setString( 3.setInt( 1..setString( 6.executeUpdate(). File file = new File( entry. //konversi foto ke byte. "alamat" ). result = sqlInsertAlamat.setString( 2. sqlInsertAlamat. ( String ) entry. sqlInsertAlamat.rollback().. if ( result == 0 ) { con. sqlInsertAlamat.kab.getNama() ).get( i ) ).get( i ) ).get( i ) ).prov. ( String ) entry.kec. sqlInsertAlamat. ( String ) entry.jalan. } //alamat.get( i ) ). ++alamatLastID ). for ( int i = 0.setBinaryStream( 3. FileInputStream fis = getFileStream( file ).length() ). entry. int result = sqlInsertOrang. ( String ) entry. sqlInsertAlamat. } Listing 4. sqlInsertOrang.setString( 4. sqlInsertAlamat. dari variabel vector int alamatLastID = getLastID( "alamat_id". ( String ) entry.get( i ) ). Studi Kasus JDBC – Adress Book 125 .getOrangID() ).setString( 8.negara. ( String ) entry.jalan. return -1.3 – Class MySQLAccess mengimplementasikan interface DataAccess untuk koneksi ke database dan melakukan interaksi dengan database. entry.setString( 5.setString( 2.getFotoPath() ). sqlInsertAlamat.executeUpdate(). if ( result == 0 ) { con.setString( 7. return -1.return fileStream. } //save to database public int saveToDatabase( AddressEntry entry ) throws SQLException { sqlInsertOrang.

return -1.//trigger->nyambung antara orang dan alamat pada //tabel orang_alamat sqlInsertOrangAlamat.telp.email.rollback(). if ( result == 0 ) { con.size().get( i ) ).setString( 3. result = sqlInsertEmail. sqlInsertEmail.clearAll(). "email" ).executeUpdate().size().setInt( 1. sqlInsertOrangAlamat.getOrangID() ).setInt( 1. //clear vector pada entry entry. entry. } } //masukkan email int emailLastID = getLastID( "email_id". i < entry.setInt( 2. entry.executeUpdate(). ++telpLastID ). i++ ) { sqlInsertEmail. sqlInsertTelp. "telp" ).getOrangID() ). i < entry. result = sqlInsertOrangAlamat. result = sqlInsertTelp.commit().executeUpdate().setInt( 2. sqlInsertEmail.setInt( 1.telp. 126 Secangkir Kopi Java . ( String ) entry. } } con.rollback(). return -1. alamatLastID ). } } //telpun int telpLastID = getLastID( "telp_id".getOrangID() ).rollback(). if ( result == 0 ) { con.setString( 3. return -1. i++ ) { sqlInsertTelp.get( i ) ). ( String ) entry. for ( int i = 0.setInt( 2. sqlInsertTelp. return 0.email. //sukses } //akhir saveToDatabase Listing 4. ++emailLastID ). if ( result == 0 ) { con.3 – Class MySQLAccess mengimplementasikan interface DataAccess untuk koneksi ke database dan melakukan interaksi dengan database. for ( int i = 0. entry.

executeQuery( query ).isLast() ) { rsOrang. entry.first().isLast() ) return -1. } return -1.previous(). return 0.last().getString( 2 ). } //first public void first() throws SQLException { rsOrang. } catch ( SQLException e ) { e. rsOrang = st. return 0.orangID = rsOrang. } //last record public void last() throws SQLException { rsOrang.CONCUR_READ_ONLY ). //nama entry. if ( rsOrang.next().isFirst() ) { rsOrang. if ( rsOrang. } //previous public int prev() throws SQLException { if ( !rsOrang.TYPE_SCROLL_INSENSITIVE.//init result set public void initView() { try { String query = "SELECT * FROM orang". } } //next public int next() throws SQLException { if ( !rsOrang. Listing 4.isFirst() ) return -1.printStackTrace().createStatement( ResultSet.3 – Class MySQLAccess mengimplementasikan interface DataAccess untuk koneksi ke database dan melakukan interaksi dengan database. ResultSet.nama = rsOrang.getInt( 1 ). } return -1. Statement st = con. } //select untuk view public AddressEntry fetchData() throws SQLException { AddressEntry entry = new AddressEntry(). 127 Studi Kasus JDBC – Adress Book .

} catch ( SQLException e ) { return null.next() ) { entry.getBytes( 3 ). while ( rsEmail.3 – Class MySQLAccess mengimplementasikan interface DataAccess untuk koneksi ke database dan melakukan interaksi dengan database.next() ) { entry. entry.executeQuery().close().addKodepos( rsAlamat. entry. entry. } //email sqlSelectEmail. } //telp sqlSelectTelp. sqlInsertEmail.next() ) { entry.addEmail( rsEmail.close(). try { imageBytes = rsOrang.close().addJalan( rsAlamat.setInt( 1. sqlInsertOrangAlamat.getInt( 1 ) ). entry. ResultSet rsTelp = sqlSelectTelp. rsOrang.addNegara( rsAlamat.close().setInt( 1. while ( rsAlamat.executeQuery(). rsOrang.addKec( rsAlamat.getInt( 1 ) ).getString( 1 ) ).getString( 6 ) ). ResultSet rsEmail = sqlSelectEmail. if ( imageBytes == null ) return null.close().getString( 7 ) ). entry. sqlInsertOrang.getString( 4 ) ).close(). rsOrang.getString( 3 ) ).addTelp( rsTelp.addProv( rsAlamat. sqlSelectAlamat. sqlSelectEmail.executeQuery().getString( 1 ) ). } return entry.getString( 2 ) ).//alamat sqlSelectAlamat.getString( 1 ) ).addDesa( rsAlamat. entry.getString( 5 ) ).getDefaultToolkit().close(). createImage( imageBytes ). ResultSet rsAlamat = sqlSelectAlamat. } //close connection public void close() { try { sqlInsertAlamat.getInt( 1 ) ).setInt( 1. } return Toolkit. 128 Secangkir Kopi Java . sqlInsertTelp.addKab( rsAlamat. while ( rsTelp. Listing 4. } //akhir method fetchData //mengambil foto public Image getImage() { byte[] imageBytes = null.

} } //untuk garbage collector protected void finalize() { close(). begitu lihat Listing 4. yaitu menjalankan perintah MAX ( column ).. Isinya sangat sederhana. } catch ( SQLException e ) { e. } } Listing 4.3 – Class MySQLAccess mengimplementasikan interface DataAccess untuk koneksi ke database dan melakukan interaksi dengan database.printStackTrace(). letak database dan mendapatkan objek Connection dengan memanggil DriverManager.sqlSelectTelp. Method getFileStream ( File file ) digunakan secara internal untuk melakukan streaming dari file untuk dimasukkan ke database dalam bentuk byte.3. Method saveToDatabase menyimpan semua entry yang dikapsulasi dalam objek AddressEntry ke dalam database sesuai dengan letak tabelnya masing-masing. Isi dari method connect() adalah melakukan penentuan driver.getConnection() dan men-set koneksi harus disubmit secara manual dengan setAutoCommit ( false ). Misalnya nama orang dimasukkan ke tabel Studi Kasus JDBC – Adress Book 129 . fungsi agregate milik SQL.close(). kamu langsung membuang buku ini. Wah. kalau kamu enggak begitu suka ama Java.close(). con.. Method ini mereturn objek FileInputStream. Method getLastID digunakan untuk mendapatkan ID terakhir dari suatu tabel.wah…aku yakin.prepareStatement ( String query ). Atau bahkan kamu nggak akan pernah baca ini karena buku ini sudah dibuang sejak kamu baca halaman pertama! ☺☺☺ Konstruktor MySQLAccess melakukan inisialisasi dengan melakukan koneksi ke database ( connect() ) dan menyiapkan statement SQL dengan Connection. yang nantinya ditambah 1 untuk membuat suatu auto_number.wah.

desain database belumlah sempurna mencapai kaidah BCNF karena aku tidak membahas soal database. Method finalize() digunakan untuk menutup koneksi yang garbage collected. Method berikutnya adalah fetchData2 yang bertugas mengambil data dari database dan dimasukkan ke objek AddressEntry. dan telp.createImage ( bytes[] imagebytes ). Adapun untuk mengambil foto dari database. sedangkan 2 method lainnya adalah void. dan prev(). first().getDefaultToolkit(). satu per satu kita mengambil data dari tabel alamat. 2 130 Secangkir Kopi Java . Harus kuakui bahwa UI ini tidak cukup user friendly. Dari situ kita returnkan sebuah objek Image dengan Toolkit. Di sini kita mengambil dari tabel orang terlebih dahulu.getXXX(). Kemudian untuk navigasi antar record ada method next(). koneksi yang lupa ditutup secara eksplisit oleh programmer. User Interface I: Class InsertForm Class ini menampilkan sebuah user interface untuk memasukkan nama baru ke dalam database. dan dengan id dari orang tersebut. Tabel Orang_Alamat merupakan tabel penyambung antara orang dan alamat karena hubungan antara dua entitas itu adalah many-to-many.orang. Sekali lagi. tapi cukuplah. Method-method ini menggerakkan ResultSet. Media penyimpanan foto ini adalah LONGBLOB – tipe data yang digunakan untuk menyimpan data yang besar seperti foto. Method first() dan last() mereturn sebuah integer untuk mendeteksi apakah record telah mencapai ujung atau belum. Kenapa aku memakai nama fetchData? Istilah untuk mengambil data dari database bukanlah get tetapi fetch. last(). sehingga ditemukan oleh si garbage collector. email. Kita ambil data dari database dengan getBytes. Kita menset parameter dari objek PreparedStatement dengan nilai yang kita ambil dari AddressEntry. artinya data yang diambil dalam bentuk array bytes. Semua koneksi ditutup dengan method close(). caranya tak kalah sederhana.

he. private JTextField txtNegara = new JTextField( 30 ). email. Listing 4.. private JTextField txtJalan = new JTextField( 30 ). Sebagai penataan komponen.*.*. Data baru akan dimasukkan ke database ketika kita menekan tombol OK. kamu harus menekan tombol Add. java.he… package addressbook. private JTextField txtProv = new JTextField( 30 ).filechooser.awt. private JTextField txtKec = new JTextField( 30 ).Gambar 4.border. aku perlu memperkenalkan layout manager yang sangat dinamis namun sulit dipelajari.2 – User Interface untuk memasukkan nama baru. javax.*. atau telepon yang lebih dari satu.4 – InsertForm untuk menambah nama baru ke dalam buku alamat Studi Kasus JDBC – Adress Book 131 .swing. public class InsertForm extends JDialog { //instans private JTextField txtNama = new JTextField( 30 ). java. import import import import import import import java.swing. private JTextField txtKab = new JTextField( 30 ).*. java..io.event.*.*. private JTextField txtDesa = new JTextField( 30 ).he.*. Untuk memasukkan data alamat. itung-itung belajar. yaitu GridBagLayout. javax. Aku belajar layout ini juga ketika menulis ini lho.awt. javax.sql.swing.

person = new AddressEntry( lastID + 1 ). private JButton btnAddEmail = new JButton( "Add" ). private JButton btnBrowse = new JButton( ".parent = parent. //layout private GridBagLayout gridBag. private JLabel lblStatus3 = new JLabel( " 0 no. //initialize try { dataAccess = new MySQLAccess().4 – InsertForm untuk menambah nama baru ke dalam buku alamat 132 Secangkir Kopi Java . private JButton btnCancel = new JButton( "Cancel" ). private boolean telpAdded = false. private JButton btnAddAlamat = new JButton( "Add" )." ).getLastID( "orang_id". public AddressEntry person. private JTextField txtEmail = new JTextField( 30 ). private JFrame parent. private int countTelp = 0. //apakah button-button add telah dipijet private boolean alamatAdded = false. private boolean emailAdded = false. private JButton btnAddNo = new JButton( "Add No. private JLabel lblStatus1 = new JLabel( " 0 alamat tersimpan" ).printStackTrace(). setTitle( "Menambah Entry Baru" ). private JPanel panel. private int countEmail = 0. createGUI(). } catch ( Exception e ) { e." ). tersimpan" ). private JLabel lblStatus2 = new JLabel( " 0 email tersimpan" ). //konstruktor public InsertForm( JFrame parent ) { this.setEnabled( false ). private JLabel lblStatus4 = new JLabel( " [kosong] " ). public JButton btnOK = new JButton( "OK" ). } //akhir konstruktor Listing 4.. private GridBagConstraints c. "orang" ). //properti untuk akses database public DataAccess dataAccess. //counter private int countAlamat = 0.private JTextField txtKode = new JTextField( 30 ). } int lastID = dataAccess. setEventHandler(). private JTextField txtNo = new JTextField( 30 ). parent.

txtKode. message = ( result == 0 ) ? "Data tersimpan dengan sukses" : "Data tidak dapat tersimpan". } } ).addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { dataAccess.this. btnAddNo. Listing 4.showMessageDialog( InsertForm. btnOK. } } ).setText( "" ). telpAdded = true. } } ).4 – InsertForm untuk menambah nama baru ke dalam buku alamat Studi Kasus JDBC – Adress Book 133 .addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { getEntry().addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { addEmail().setText( "" ).setText( "" ). btnAddAlamat. txtEmail.setEnabled( true ).saveToDatabase( person ). InsertForm. txtNegara. message ).setText( "" ). } } ). try { int result = dataAccess. txtProv.this. txtKab.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { addTelp(). txtKec. //clear text field txtJalan.setText( "" ).private void setEventHandler() { btnCancel.setText( "" ). String message = "". txtNo.setText( "" ).addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { addAlamat(). alamatAdded = true.dispose(). parent. emailAdded = true. txtDesa. JOptionPane.close(). btnAddEmail.setText( "" ).setText( "" ).

} } } ). addWindowListener(new WindowAdapter() { public void windowClosing ( WindowEvent e ) { dataAccess. InsertForm. lblStatus4. "jpg"}. } //menampilkan file dialog private void showFileDialog() { String[] allImage = { "bmp". "gif".addChoosableFileFilter( filterBMP ).this. fileChooser.addChoosableFileFilter( filterJPG ). } catch ( SQLException sql ) { message = "Data tidak dapat tersimpan".APPROVE_OPTION ) { File file = fileChooser. InsertForm.addChoosableFileFilter( filterGIF ).dispose().printStackTrace().parent. sql. FileFilter filterJPG = new FileFilter( "jpg".close().this.showMessageDialog( InsertForm. FileFilter filterAll = new FileFilter( allImage. fileChooser. } } ).getAbsolutePath() ). FileFilter filterGIF = new FileFilter( "gif". fileChooser. fileChooser. JOptionPane.setEnabled( true ). message ).this. "Supported Image" ). } } Listing 4.getSelectedFile(). btnBrowse. parent.addChoosableFileFilter( filterAll ).showOpenDialog( this ) == JFileChooser. "Bitmap Image" ).addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { showFileDialog(). JFileChooser fileChooser = new JFileChooser().4 – InsertForm untuk menambah nama baru ke dalam buku alamat 134 Secangkir Kopi Java .dispose().setEnabled( true ). if ( fileChooser. "JPG Image" ). "GIF Image" ). } }).setText( file. //file filter FileFilter filterBMP = new FileFilter( "bmp".

getText() ).getText() ).getText() ).getText() ).addEmail( txtEmail.addDesa( txtDesa. //nama person. } Listing 4.setText( " " + countAlamat + " alamat tersimpan" ).getText(). person.equals( "" ) ) { person.addProv( txtProv. } } //add telp ke vector private void addTelp() { if ( !txtNo. lblStatus1.addTelp( txtNo. person. person.addNegara( txtNegara.setText( " " + countTelp + " no.addKab( txtKab. if ( !telpAdded ) addTelp().equals( "" ) ) { person.getLastID( "orang_id". person.getText() ).//memasukkan alamat ke vector private void addAlamat() { person.4 – InsertForm untuk menambah nama baru ke dalam buku alamat Studi Kasus JDBC – Adress Book 135 . } //add email ke vector private void addEmail() { if ( !txtEmail. person.addKodepos( txtKode. "orang" ). countEmail++.getText() ).setNama( txtNama.setFotoPath( lblStatus4. lblStatus3. if ( !emailAdded ) addEmail().setOrangID( lastID + 1 ). //alamat if ( !alamatAdded ) addAlamat().addJalan( txtJalan.addKec( txtKec. person. countTelp++. lblStatus2. person.getText() ). } } //mengambil nilai dari text field public AddressEntry getEntry() { //id int lastID = dataAccess. countAlamat++.getText() ).setText( " " + countEmail + " email tersimpan" ).getText() ). tersimpan" ).getText() ). return person. person.getText() ).getText().

txtKode ). lblEmail. //label addRow( addRow( addRow( addRow( addRow( addRow( addRow( + text field new JLabel( "Jalan: " ).0. //button + label status lblStatus1.gray ) ). //button + label status lblStatus3.setMnemonic( 'A' ). //vertical extra space addRow( new JLabel( "Nama: " ). txtNama ). txtProv ).setBorder( new LineBorder( Color.4 – InsertForm untuk menambah nama baru ke dalam buku alamat 136 Secangkir Kopi Java . lblStatus2 ).setBorder( new LineBorder( Color. c.gray ) ). txtNegara ). txtDesa ).gray ) ).gray ) ). addRow( new JLabel( "No: " ). JLabel lblTelp = new JLabel( "No Telp: " ). //label alamat JLabel lblAlamat = new JLabel( "Alamat: " ).gray ) ).setBorder( new LineBorder( Color.fill = GridBagConstraints. //email address JLabel lblEmail = new JLabel( "Email Address: " ). new JLabel( "Desa: " ). addButtonAndStatus( btnAddEmail.setMaximumSize( new Dimension( 10. txtNo ).BOTH. txtJalan ). txtEmail ). new JLabel( "Provinsi: " ). txtKab ).setBorder( new LineBorder( Color. //pasang komponen --> setting constraints //label nama JLabel lblNama = new JLabel( "Nama: " ). c = new GridBagConstraints(). c. new JLabel( "Kabupaten: " ).private void createGUI() { gridBag = new GridBagLayout(). btnAddNo. //no telp. addSingleComponentInRow( lblEmail ). //button + label status lblStatus2. addSingleComponentInRow( lblTelp ).setBorder( new LineBorder( Color. addRow( new JLabel( "Email: " ). addButtonAndStatus( btnAddAlamat.weighty = 1.setMnemonic( 'd' ). new JLabel( "Kode Pos: " ).setMnemonic( 'N' ). new JLabel( "Kecamatan: " ). lblStatus1 ). panel = new JPanel( gridBag ). addSingleComponentInRow( lblAlamat ). txtKec ). lblTelp. new JLabel( "Negara: " ). lblAlamat. Listing 4. lblStatus3 ). 10 ) ). btnAddAlamat.gray ) ).setBorder( new LineBorder( Color. addButtonAndStatus( btnAddNo. btnAddNo. btnAddEmail.

setConstraints( label.0. BorderLayout.1. panel2. gridBag. panel2. btnCancel.REMAINDER. 460 ).//foto c. fl. contPane. //text field c. c. JPanel panel3 = new JPanel( new FlowLayout( FlowLayout.EAST ).weightx = 0. contPane.9. c.setFont( new Font( "Arial". c. 11 ) ).add( btnBrowse ). BorderLayout.setMaximumSize( new Dimension( 20. JPanel panel2 = new JPanel( fl ). panel.WEST ). c.RIGHT ).add( panel3.add( label ).add( panel2 ).setConstraints( lblFoto. setSize( 350. gridBag.0. //text field foto FlowLayout fl = new FlowLayout( FlowLayout.setHgap( 0 ). c ).gridwidth = GridBagConstraints.weightx = 0. BorderLayout. 18 ) ). c ).gridwidth = GridBagConstraints.REMAINDER.add( panel.CENTER ). c. getRootPane(). setVisible( true ).setMnemonic( 'C' ).SOUTH ).gridwidth = GridBagConstraints. Font. btnBrowse.add( btnCancel ). JComponent txtField ) { c. Listing 4.weightx = 1.setConstraints( panel2. 18 ) ). //button ok dan cancel btnOK. panel3.4 – InsertForm untuk menambah nama baru ke dalam buku alamat Studi Kasus JDBC – Adress Book 137 . panel3.RELATIVE.setMnemonic( 'O' ). //buat gap contPane.setPreferredSize( new Dimension( 20.BOLD. BorderLayout.weightx = 0.gridwidth = 1.add( lblFoto ). gridBag.add( new JPanel().add( lblStatus4 ).add( new JPanel().setDefaultButton( btnOK ). panel. Container contPane = getContentPane(). contPane. } //tambah label dan text field private void addRow( JComponent label.RIGHT ) ). JLabel lblFoto = new JLabel( "Foto: " ). btnBrowse. lblStatus4. c ). panel.add( btnOK ).

Pada method showFileDialog() yang digunakan untuk menampilkan dialog membuka file. diasumsikan field alamat. panel. JComponent comp2 ) { c.gridwidth = 1.REMAINDER.setConstraints( txtField.REMAINDER.add( comp ).setConstraints( comp2.0. panel. Di situ ada blok if yang menunjukkan jika user belum menekan tombol Add. Method getEntry() memindahkan data-data yang ada pada text field ke dalam objek AddressEntry. gridBag.add( comp1 ).gridwidth = GridBagConstraints.setConstraints( comp1. Tetapi karena keterbatasan halaman. Konstruktor melakukan inisialisasi objek DataAccess untuk akses database. c ). panel. c. gridBag. c.weighty = 0. } } Listing 4. c ). panel.gridwidth = GridBagConstraints. membuat user interface dan menset event yang terjadi pada tiap-tiap komponen.0. InsertForm merupakan subclass dari JDialog. 138 Secangkir Kopi Java . c ). } //tambah button 'add' dan label status private void addButtonAndStatus( JComponent comp1. c. aku menunjukkan penambahan file filter pada kotak dialog tersebut supaya hanya membuka file yang dimaksud.gridBag. dan telp hanya satu buah. email. gridBag.add( comp2 ). } //tambah label thok private void addSingleComponentInRow( JComponent comp ){ c.4 – InsertForm untuk menambah nama baru ke dalam buku alamat Well. sehingga langsung ditambahkan ke Vector. inisialisasi objek AddressEntry. aku tidak menjelaskan isi class FileFilter secara mendetail.setConstraints( comp. c ).weightx = 0.add( txtField ).

Masing-masing komponen memiliki GridBagConstraints yang bisa berbeda untuk mengatur letak komponen tersebut. 4. Misalnya: fill = GridBagConstraints. Misalnya dalam 1 baris ada 6 cell. NORTHEAST. jika komponen menempati cell 3. dan NORTHWEST. maka 3. NORTH. gridwidth. Nilai yang valid adalah CENTER. GridBagLayout Pada method createGUI() pada InsertForm ( listing 4. Studi Kasus JDBC – Adress Book 139 .Memperkenalkan. RELATIVE. gridheight: Digunakan untuk menentukan jumlah cell dalam satu baris (gridwidth) atau kolom (gridheight). Nilai yang valid adalah: n. Kamu harus menset beberapa properti dari objek GridBagConstraints untuk menggunakan layout GridBagLayout secara efektif. RELATIVE: Komponen akan mengambil semua cell yang tersisa kecuali yang terakhir. SOUTHWEST. Masing-masing komponen yang diatur oleh GridBagLayout berhubungan dengan sebuah instance dari GridBagConstraints. GridBagLayout menempatkan komponen baik secara vertikal maupun horizontal tanpa membuat komponen harus memiliki ukuran yang sama pada display area. insets: Digunakan untuk menentukan jumlah spasi luar (external padding) antara komponen dan display area. dalam pixel. n adalah jumlah angka dalam integer. 5 dia pakai.BOTH.CENTER. dan VERTICAL. WEST. Nilai yang valid adalah NONE. untuk memasang komponen pada panel aku menggunakan layout manager GridBagLayout. SOUTHEAST. EAST.4 ). REMAINDER. Misalnya: anchor = GridBagConstraints. fill: Digunakan untuk memberitahu layout manager bagian mana yang harus direntangkan (stretch) ketika display area lebih besar dari ukuran normal komponen. HORIZONTAL. BOTH. Properti tersebut antara lain: anchor: Digunakan untuk memberitahu layout manager di mana harus meletakkan komponen ketika komponen lebih kecil daripada display area.

dengan ipadx = 4 dan ipady = 5. REMAINDER 1 2 3 4 5 6 RELATIVE ipadx. aku menggunakan format HTML. dan addSingleComponentInRow(). gridx = 0 dan gridy = 0 berarti komponen terletak pada cell pertama (pojok kiri atas) dari grid.0 – 1. Pada method createGUI(). gridx. 1. karena class ViewPane merupakan subclass dari class JEditorPane. addButtonAndStatus().REMAINDER: Komponen merupakan komponen terakhir dalam satu baris atau kolom.0 berarti komponen tidak mendapatkan ruang (tetap). addRow(). ipady: Merupakan spasi internal (internal padding). maka ukuran total komponen menjadi 34 x 25 pixel.0 berarti komponen mendapat semua ruang tambahan. kita menambahkan komponen pada panel. Membangun User Interface II: Class ViewPane Untuk menampilkan data tiap nama dari database. kita mengubah beberapa properti dari GridBagConstraints kemudian kita pasang ke GridBagLayout dengan setConstraints(). Jika komponen memiliki panjang 30 pixel dan lebar 20 pixel. 0. Nilai yang valid adalah tipe double antara 0. weighty: Menentukan bagaimana membagi ruang tambahan ketika komponen di-resize. Dan lagi-lagi mengunakan JEditorPane sebagai alat yang siap pakai. Barulah setelah siap semuanya. gridy: Menentukan letak pojok kiri atas komponen. weightx.0. sebelum memasang suatu komponen. 140 Secangkir Kopi Java .

dataAccess.printStackTrace(). java. } //navigasi public void first() { try { dataAccess. Studi Kasus JDBC – Adress Book 141 .*. } catch ( Exception e ) { e.first().*. entry = dataAccess. dataAccess.fetchData().fetchData(). import import import import java.*.printStackTrace(). } catch ( Exception e ) { e. buildPage().first().*. entry = dataAccess. buildPage(). java.awt. try { dataAccess = new MySQLAccess().initView(). entry = dataAccess.package addressbook.swing.fetchData(). dataAccess.initView().awt.printStackTrace(). buildPage(). } } Listing 4.event. } } //refreshing data public void refresh() { try { dataAccess.io.first(). } catch ( Exception e ) { e. } } //foto public Image getImage() { return dataAccess. public class ViewPane extends JEditorPane { private DataAccess dataAccess. javax.5 – Class ViewPane merupakan anak dari JEditorPane yang digunakan untuk menampilkan data orang yang ada di database. private AddressEntry entry. //konstruktor public ViewPane() { setEditable( false ).getImage().

} catch ( Exception e ) { e.printStackTrace().fetchData(). } catch ( Exception e ) { e.getNama() ).fetchData().next(). Listing 4. 142 Secangkir Kopi Java . } catch ( Exception e ) { e. try { code = dataAccess. entry = dataAccess. } public int prev() { int code = 0. buildPage().append( "<strong>" ). entry = dataAccess. script.printStackTrace().append( "<div align='center'>" + "<font face='Comic Sans MS' size='3'>" ). } public void closeDatabase() { dataAccess. try { code = dataAccess. entry = dataAccess.append( "Nama: " ). script. script.5 – Class ViewPane merupakan anak dari JEditorPane yang digunakan untuk menampilkan data orang yang ada di database. script.close(). buildPage(). //nama script.public void last() { try { dataAccess.printStackTrace(). } return code. } private void buildPage() throws Exception { StringBuffer script = new StringBuffer().fetchData(). buildPage(). } } public int next() { int code = 0. } return code.append( entry.append( "<html><body bgcolor='#F0F4F0' " + "leftmargin='0' topmargin='0'>" ).last().prev().

kodepos.telp. for ( int i = 0.append( temp + "<br>" ). " ).telp. if ( !(temp = (String) entry. } } Listing 4.jalan.append( "Email:<br>" ). } //email script. for ( int i = 0. i < entry.get( i ) + "<br>" ).append( "<br><br>Alamat: <br>" ).desa. i++ ) { script.telp.append( "</body></html>" ). script. script. script.<br>" ).equals( "" ) ) script. script. 143 Studi Kasus JDBC – Adress Book .kec.size().append( "Desa/Kel: " + ( String ) entry.size().5 – Class ViewPane merupakan anak dari JEditorPane yang digunakan untuk menampilkan data orang yang ada di database. for ( int i = 0. script.negara.toUpperCase() + "<br>" ).append(( (String) entry. script.append( "0" + ( i + 1 ) + ". setContentType( "text/html" ).append( temp + "<br>" ). i < entry.append( "</font></div>" ).append( "Kecamatan: " + ( String ) entry.get( i ) + "<br>" ).get( i ) + "<br>" ). } script.append( "Kabupaten/Kota: " + ( String ) entry. setCaretPosition(1).size() . String temp = "".append( "<br>Telp:<br>" ). script. if ( i != entry.email. i++ ) { script.append( ".get( i ) ). script. i < entry.get( i ) ). if ( !( temp = ( String ) entry.toString() ).kab.prov. i++ ) { script.get( i ) ).append( ( String ) entry.append( ( String ) entry.size().append( "<br>" ).get( i ) + "<br>" ).desa.1 ) script. setText( script.equals( "" ) ) script.append( "Provinsi: " + ( String ) entry.get( i ) + "<br>" ). } //telp script.//alamat script.get(i)) .email.append( "</strong>" ).

3 – Tampilan ViewPane setelah diisi script dengan format HTML 144 Secangkir Kopi Java . last(). Setelah semua selesai. Method buildPage() sendiri merupakan penyusun script HTML untuk ditampilkan di JEditorPane. Penyusun script-nya memakai StringBuffer. Hal yang sama dilakukan pada method refresh(). next(). Setelah itu mengisi objek AddressEntry dengan fetchData().first() untuk mengarahkan record ke posisi pertama. JEditorPane content-type-nya diset “text/html”. dan prev() mengarahkan dataAccess Dari situ kita akan dan kemudian mengisi objek membangun halaman dengan DataEntry.initView() untuk melakukan query dan memanggil dataAccess. “text/plain” untuk format teks biasa. dia akan memanggil buildPage() untuk menyusun datadata dalam format HTML. Kemudian. karena sudah terbentuk di konstruktor. Gambar 4. Ada tiga macam content type pada JEditorPane yaitu: “text/html” untuk format HTML. buildPage(). dan “text/rtf” untuk format RTF (Rich Text Format). bedanya ia tidak membuat objek dataAccess yang baru. Method-method navigasi seperti first().Konstruktor ViewPane melakukan inisialisasi dengan membuat objek DataAccess dan langsung memanggil method dataAccess.

javax. private Action firstAction = new FirstAction(). private Action prevAction = new PrevAction(). import import import import java.border. java.awt. Class ini menyediakan tombol dan menu-menu untuk menjalankan class-class yang telah kita buat.4 – Tampilan awal aplikasi yang telah kita buat dengan susah payah package addressbook. private JMenu navMenu. 145 Studi Kasus JDBC – Adress Book . Gambar 4. private Action nextAction = new NextAction(). javax. private Action viewContactAction = new ViewContactAction().*.swing.*.swing.awt.event. Listing 4.Membangun User Interface Utama: Class AddressBook Sekarang tiba saatnya untuk mengumpulkan user interface yang telah kita buat dalam satu aplikasi Address Book.*. //main class public class AddressBook extends JFrame { //instans private Action newDataAction = new NewDataAction().*. private Action lastAction = new LastAction().6 – Aplikasi AddressBook yang menyebabkan kita bisa berinteraksi dengan database.

setMnemonic( 'A' ). JMenu helpMenu = new JMenu( "Help" ). navMenu. navMenu = new JMenu( "Navigasi" ). message ). menuBar.exit( 0 ).setMnemonic( 'N' ). JOptionPane.add( helpMenu ). //menu JMenuBar menuBar = new JMenuBar().setEnabled( false ). dataMenu.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { String message = "Studi Kasus JDBC-Untuk Buku Secangkir" + "Kopi Java\n(c) Fatso--20 Agustus 2004" + ". JMenu dataMenu = new JMenu( "Data" ).addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { System.\nParuh terakhir liburan semester IV".add( viewContactAction ). JToolBar toolBar. navMenu. dataMenu. exitMenu. JMenuItem helpAbout = new JMenuItem( "About" ). navMenu. } } ).add( dataMenu ). helpAbout. dataMenu. menuBar.private private private private private ImagePanel panelBack. JLabel lblFoto = new JLabel().setMnemonic( 'H' ).setMnemonic( 'K' ). 146 Secangkir Kopi Java . boolean initialized = false. navMenu.add( firstAction ).6 – Aplikasi AddressBook yang menyebabkan kita bisa berinteraksi dengan database.add( exitMenu ). menuBar.add( nextAction ). dataMenu.setMnemonic( 'D' ). ViewPane viewPane.add( prevAction ).add( navMenu ). helpAbout. dataMenu. public AddressBook() { super( "Address Book Aplication" ).add( helpAbout ). JMenuItem exitMenu = new JMenuItem( "Keluar" ). } }).add( newDataAction ). navMenu. navMenu.addSeparator(). exitMenu. helpMenu. Listing 4.showMessageDialog( AddressBook. helpMenu.this.add( lastAction ).

repaint(). Studi Kasus JDBC – Adress Book 147 . } public void viewEntry() { if ( !initialized ) { viewPane = new ViewPane(). } } ). setVisible( true ).//toolbar toolBar = new JToolBar().NORTH ). //container panelBack = new ImagePanel( getClass().setText( "Tidak Ada Foto" ). if ( image != null ) { ImageIcon imageIcon = new ImageIcon( viewPane. navMenu. } else { lblFoto.6 – Aplikasi AddressBook yang menyebabkan kita bisa berinteraksi dengan database.jpg" ) ).add( newDataAction ).getImage(). BorderLayout.setEnabled( true ).add( toolBar.add( firstAction ). //closing window addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent e ) { viewPane.add( toolBar. BorderLayout. prevAction ). setJMenuBar( menuBar ). JScrollPane scrPane = new JScrollPane( viewPane ). Container cp = getContentPane(). //toolbar toolBar. lblFoto. addFoto(). toolBar. } private void addFoto() { //foto Image image = viewPane. toolBar.add( toolBar.getImage() ). lblFoto.setIcon( imageIcon ). setDefaultCloseOperation( EXIT_ON_CLOSE ).add( toolBar. nextAction ).setText( "" ). cp. } lblFoto. 500 ). Listing 4. lastAction ).add( panelBack.CENTER ).add( viewContactAction ).closeDatabase(). setSize( 700. cp. lblFoto.setIcon( null ).getResource( "icons/back.

} } private class FirstAction extends AbstractAction { public FirstAction() { putValue( Action. } } public static void main( String[] main ) { new AddressBook().first().getResource( "icons/first. nextAction. new Integer( 'A' ) ). BorderLayout.EAST ).png" ) ) ). contPane. putValue( Action. 148 Secangkir Kopi Java . "Awal Records" ).createLineBorder( Color.add( lblFoto.setBorder( BorderFactory.setEnabled( true ).SMALL_ICON. BorderLayout. putValue( Action.NAME. contPane.6 – Aplikasi AddressBook yang menyebabkan kita bisa berinteraksi dengan database. 4 ) ).remove( panelBack ). addFoto().SMALL_ICON. contPane. } } Listing 4. initialized = true.repaint(). Container contPane = getContentPane().lblFoto.SHORT_DESCRIPTION.MNEMONIC_KEY. prevAction. new Integer( 'T' ) ).validate().CENTER ). contPane. "Awal" ).this ). } else { viewPane. "Menambah entri baru" ). putValue( Action. new ImageIcon( getClass().refresh().black. contPane. } private class NewDataAction extends AbstractAction { public NewDataAction() { putValue( Action. addFoto().setEnabled( false ). "Tambah Baru" ).getResource( "icons/filenew.NAME. } public void actionPerformed( ActionEvent e ) { new InsertForm( AddressBook. putValue( Action.MNEMONIC_KEY. new ImageIcon( getClass().png" ) ) ).add( scrPane.SHORT_DESCRIPTION. putValue( Action. } public void actionPerformed( ActionEvent e ) { viewPane. putValue( Action.

new ImageIcon( getClass().last(). } public void actionPerformed( ActionEvent e ) { int code = viewPane.setEnabled( true ).NAME. prevAction. } public void actionPerformed( ActionEvent e ) { viewPane.SHORT_DESCRIPTION. "Selanjutnya" ).MNEMONIC_KEY. "Akhir" ).private class PrevAction extends AbstractAction { public PrevAction() { putValue( Action.SMALL_ICON.setEnabled( false ).MNEMONIC_KEY.SMALL_ICON.getResource( "icons/prev. putValue( Action. new Integer( 'B' ) ). putValue( Action. } } private class NextAction extends AbstractAction { public NextAction() { putValue( Action. new ImageIcon( getClass(). nextAction. } public void actionPerformed( ActionEvent e ) { int code = viewPane. "Record Selanjutnya" ).NAME.png" ) ) ). addFoto(). nextAction. new Integer( 'L' ) ). if ( code == -1 ) setEnabled( false ). new ImageIcon( getClass(). putValue( Action. putValue( Action.next().prev().MNEMONIC_KEY. "Akhir Records" ). putValue( Action. setEnabled( false ). } } private class LastAction extends AbstractAction { public LastAction() { putValue( Action.6 – Aplikasi AddressBook yang menyebabkan kita bisa berinteraksi dengan database.SMALL_ICON. putValue( Action.png" ) ) ).getResource( "icons/last. putValue( Action. new Integer( 'K' ) ).NAME. addFoto().setEnabled( true ). Studi Kasus JDBC – Adress Book 149 . putValue( Action. putValue( Action.SHORT_DESCRIPTION.SHORT_DESCRIPTION. "Sebelumnya" ).getResource( "icons/next.png" ) ) ). Listing 4. "Record Sebelumnya" ).

well.6 – Aplikasi AddressBook yang menyebabkan kita bisa berinteraksi dengan database. kemudian memasang pada JLabel.setEnabled( true ). prevAction.NAME. Well.SHORT_DESCRIPTION. new ImageIcon( getClass(). Perhatikan kembali pada method viewEntry(). } } //akhir private class } //akhir class AddressBook Listing 4.. } } private class ViewContactAction extends AbstractAction { public ViewContactAction() { putValue( Action.MNEMONIC_KEY. Untuk method viewEntry().if ( code == -1 ) setEnabled( false ). addFoto(). viewEntry() hanya melakukan refreshing. kamu harus memanggil method validate() agar panel yang baru dipasang segera tampak di layar. putValue( Action.getResource( "icons/fileopen. NextAction. putValue( Action. Setelah melakukan pergantian panel.. aku me-remove panel berbackground (dari class ImagePanel) dan menggantinya dengan panel viewPane dan lblFoto. } public void actionPerformed( ActionEvent e ) { viewEntry().SMALL_ICON. yaitu pada konstruktor dan pada method viewEntry(). LastAction. "Melihat Daftar" ). hanya sedikit yang perlu dijelaskan di sini. Inisialisasi dilakukan di dua tempat. inisialisasi dilakukan pada saat Action viewContact diaktifkan. bukan inisialisasi lagi. putValue( Action. Method addFoto() memasang foto pada form. NewDataAction bertugas memunculkan 150 Secangkir Kopi Java .png" ) ) ). Dia membuat ImageIcon dari objek Image yang didapat dari database. Jika action tersebut ditekan lagi. Class-class internal semuanya mengatur tentang Action yang mengatur navigasi antar record seperti FirstAction. "Melihat Daftar" ). new Integer( 'M' ) ). dan PrevAction.

} public void createImage( URL url ) throws Exception { image = Toolkit.awt. private URL pathURL.*.*. Studi Kasus JDBC – Adress Book 151 . untuk menampilkan JPanel yang memiliki background gambar.7 – Class ImagePanel. java. Sedangkan class ViewContactAction bertugas menampilkan data-data orang beserta fotonya yang disusun oleh ViewPane dan JLabel.event. javax. Inilah jawaban yang kulakukan sebisaku… package addressbook. } catch ( Exception e ) { e.*. javax. javax.printStackTrace().net. import import import import import import import java.*.swing. java.*.*. java. private Image image.dialog InsertForm. Listing 4. } } public URL getURL() { return pathURL.swing.getDefaultToolkit(). Aku sering ditanyai teman-temanku bagaimana caranya memasang background image pada aplikasi Java layaknya aplikasi VB.image. Class-Class Pendukung Class ImagePanel Class ini merupakan subclass dari JPanel yang bertujuan menampilkan background dari panel tersebut.awt.event.createImage( url ).*. public class ImagePanel extends JPanel { //image private BufferedImage origImage.swing. createImage( url ). //constructor public ImagePanel( URL url ) { try { pathURL = url.border.awt.

graphics. graphics. } //get width public int getWidth() { return origImage. 0. } } Listing 4. } Graphics2D graphics = origImage.setPreferredSize( new Dimension( 60.7 – Class ImagePanel. BufferedImage. try { medTrack.addImage( image. Graphics2D graphics = ( Graphics2D ) g. } //draw image panel public void paintComponent( Graphics g ) { super.getHeight(). 0. } //get preffered size public Dimension getPreferredSize() { return new Dimension( origImage.createGraphics(). super.paintComponent( g ). medTrack. 152 Secangkir Kopi Java .MediaTracker medTrack = new MediaTracker( this ).TYPE_INT_RGB ).waitForAll(). super. } catch ( Exception e ) { e. origImage = new BufferedImage( image. untuk menampilkan JPanel yang memiliki background gambar. 60 ) ). image.setBorder( BorderFactory. null ). null ).printStackTrace().createLoweredBevelBorder() ). } //get height public int getHeight() { return origImage.drawImage( origImage. origImage.getHeight() ). 0 ). } //get minimum size public Dimension getMinimumSize() { return getPreferredSize().getWidth( null ).getWidth().getHeight( null ). null.drawImage( image.getWidth().

Bukan aku sendiri yang menulis class ini.java Studi Kasus JDBC – Adress Book 153 . Class FileFilter Class FileFilter digunakan untuk menentukan tipe file apa saja yang muncul pada kotak dialog JFileChooser. bisa audio. BufferedImage digunakan untuk membuat objek Graphics2D yang bertugas menggambar image pada panel. Kita perlu meng-override method paintComponent untuk menggambar kembali image dengan method drawImage.getDefaultToolkit(). Letaknya di [JAVA_HOME]/demo/jfc/FileChooserDemo/src/ ExampleFileFilter. MediaTracker berfungsi untuk melakukan penelusuran (tracking) pada suatu media. Proses selanjutnya adalah membuat BufferedImage dari Image yang sudah diregister ke MediaTracker sebagai image yang bertipe RGB (Red Green Blue). Pertama-tama sumber dari URL diubah menjadi objek Image dengan Toolkit. tetapi Sun Microsystem. Kemudian kita meregister image tersebut ke objek MediaTracker. Method getPreferredSize() juga di-override agar mengembalikan nilai ukuran dari image. Objek Image dapat digambar pada panel dengan memanggil method drawImage.7) adalah method createImage() yang memproses gambar dari URL (Uniform Resource Locator) menjadi background. Kamu bisa mendapatkan source code class ini di demo-nya Java 2 SDK.createImage ( URL url ). supaya image tidak kelihatan terpotong.Inti dari class ini (Listing 4. bisa image.

tapi paling tidak sudah dapat menunjukkan bagaimana JDBC berinteraksi dengan database. Ringkasan Kamu telah mempelajari bagaimana membuat sebuah aplikasi nyata mengenai JDBC.5 – Tampilan keseluruhan dari aplikasi AddressBook setelah kita jalankan iv. Tugasmu adalah memperbaikinya. Memang masih banyak kekurangan yang terdapat pada aplikasi ini.Gambar 4. Oce?!?! 154 Secangkir Kopi Java .

Appendix A Mendistribusikan Aplikasi Java dengan Java Archive ( JAR ) .

.

kita mendapatkan banyak sekali class-class yang mendukung aplikasi kita. Tool untuk membuat file JAR telah dibundel dalam Java 2 Standard Development Kit (dulu dikenal dengan JDK) di bawah folder [JAVA_HOME]/bin bersama file-file javac. Byte code tersebut disimpan dalam sebuah file berekstensi *. Kita bisa ditertawakan oleh programmer C++ atau VB yang hasil akhir aplikasinya adalah file *. File JAR juga membuat kita dapat melakukan digital signing untuk mengamankan class-class kita dari yang tidak berhak (ehm).exe yang tinggal klik 2 kali untuk menjalankan. java.1) atau stdout (versi 1.2) apa saja yang dilakukan ketika file JAR dibuat.Untuk memenuhi syarat multi-platform-nya. Membuat File JAR Format dasar untuk membuat file JAR adalah: jar cvf nama-jar-file.class. dkk. File JAR adalah file yang mirip dengan file ZIP dengan fungsi tambahan berupa Manifest file. aplikasi-aplikasi Java dikompilasi menjadi byte code yang diinterpretasikan oleh Java Virtual Machine. Main-class maksudnya class di mana terdapat method sakti: public static void main (String[] args). : Mengeluarkan output pada stderr (versi 1. javah.jar input-file Keterangan: c v : Menandakan kita membuat file JAR baru. sehingga ketika aplikasi kita jadi. Seringkali kita membuat sebuah aplikasi yang terdiri lebih dari satu class untuk memudahkan enkapsulasi data. Manifest file adalah file teks yang menunjukkan dimanakah main-class berada. Tentunya tidak praktis untuk mendistribusikan class-class tersebut ke end-user yang kebanyakan tidak memiliki pengetahuan khusus tentang Java. Java memiliki cara untuk mengumpulkan class-class tersebut dalam file yang disebut Java Archive (JAR). Appendix A – Mendistribusikan Aplikasi Java dengan JAR 157 .

. bukan pada standard output ( stdout). misalnya terletak di F:\Java\JDBC\classes\addressbook. buka AddressBook.jar addressbook/* 2.jar : Nama file JAR yang akan kita buat. nama-jar-file. Untuk file lebih dari satu dipisahkan dengan.jar yang jika kita klik dua kali akan menjalankan main-class-nya..class(in = 688) (out= 393)(deflated 42%) adding: addressbook/AddressBook$2. terbuat file JAR baru bernama AddressBook. pastikan file manifest. Contoh: Aplikasi yang kita buat pada bab tiga menghasilkan class-class yang berada pada struktur directory seperti di bawah ini: + addressbook ----+ Letak file *. Lakukan seperti di bawah ini: F:\Java\JDBC\classes> jar cvf AddressBook.jar dengan alat kompresi seperti WinRAR. coba menjalankannya dengan perintah [JAVA_HOME]/bin/jar cvf AddressBook. F:\Java\JDBC\classes> _ >> catatan: jika perintah jar tidak dikenali.mf di bawah folder META-INF berbunyi seperti di bawah ini: 158 Secangkir Kopi Java . juga menerima directory dan WildCards ( * ).jar addressbook/* added manifest adding: addressbook/AddressBook$1. arahkan ke direktori tempat folder AddressBook berada.class(in = 920) (out= 561)(deflated 39%) . Input-file : File-file yang kita tambahkan pada JAR file... Tetapi jika gagal. arahkan ke classes.dst. Buka command prompt. 1.class ----+ icons --------+ Letak file untuk icon Kita akan membundelnya dalam file JAR. Mestinya.f : Menandakan bahwa hasil disimpan di file.

[archived-file(s)] adalah filefile yang diekstrak.jar. Meng-update file JAR bernama file. Untuk command line. maka file tersebut akan di-overwrite Keterangan Melihat isi dari file JAR bernama jar- Menjalankan Aplikasi yang Dibundel dalam JAR Jika dalam komputer client sudah terdapat Java SDK atau Java Runtime Environment.jar inputfile(s) dengan file input input-file(s).jar file. kamu perlu menambahkan tag-tag berikut di dalam tag <applet> Appendix A – Mendistribusikan Aplikasi Java dengan JAR 159 .jar Untuk applet yang dibundel dalam file JAR. ketika kita klik 2 kali pada explorer.jar Meng-ekstrak file JAR bernama jarjar xf jar-file.jar. Mengupdate file JAR bernama file.Manifest-Version: 1.AddressBook Perintah JAR Lainnya Di bawah ini adalah beberapa perintah tool JAR yang lain: Perintah jar tf jar-file.2 ke atas bisa diketik seperti di bawah ini: java –jar filejar.jar [archived-file(s)] file. khusus untuk JRE versi 1.jar dengan manifest file baru bernama jar cmf manifest-file file.0 Main-Class: addressbook.jar Jar uf file.jar input-file(s) manifest-file dan dengan file input bernama input-file(s). untuk file input lebih dari satu dipisah dengan spasi. maka aplikasi sudah bisa berjalan secara ostosmastis – dengan syarat manifest-file-nya sudah benar. Jika input-file sudah ada pada file.

kita cek dulu apakah ada Java Runtime Environment di sana.com). jika kita bisa membuat *. yang kita lakukan dalam *.class archive=filejar.com) atau Install Anywhere (http://zerog. kita tidak bisa memaksa aplikasi Java menjadi executable ala Windows dengan membuat file *. dan csh (C shell). Kita bisa membuat sendiri installer-nya. Kita hanya bisa membuat file *.jar width=120 height=120> </applet> JAR adalah hasil akhir dari sebuah aplikasi Java. jika nggak mau repot. ataupun WinACE 2. kita bisa memakai utility installer dari Installshield Wizard (http://www. tetapi yang bersifat native – platform dependent – seperti Visual C++ di Windows ataupun C++ dengan kompiler gcc di Linux. tetapi kusarankan jangan memakai bahasa Java. Atau. Maksudku. 160 Secangkir Kopi Java . WinZIP. Shell yang paling sering digunakan adalah sh (bourne shell – biasa disebut shell).exe. Sebelum kita menanamkan aplikasi kita ke komputer user. baik juga bagi kita untuk menyertakan installer-nya. Jika kita pengguna Microsoft Windows.<applet code=MainClass.exe. bash (bourne-again shell).installshield.exe asli. Jika kamu pengguna UNIX dan keluarganya. File *.jar” ke dalam executable *. Menanamkan command line “java –jar filejar.exe yang tidak sepenuhnya *.exe itu adalah: 1. Kita bahas Shell di UNIX lain kali yach! Dalam mendistribusikan aplikasi Java. tanamkan command line ke dalam file shell script.exe ataupun ke dalam batch file (*. jika belum kita install-kan dulu JRE-nya.bat). Meng-kompres file JAR menjadi self-extracting.exe seperti ini dapat dikenali dengan membukanya dengan utility kompresing seperti WinRAR.

Appendix B Instalasi Java 2 Standard Development Kit (J2SDK) dan Tentang Packaging .

.

4. Nah. J2SDK memiliki versi 1.2.*. Biasanya merupakan class-class yang dibundel dalam file JAR di bawah folder [JAVA_HOME]/jre/lib.jar.2\jre\lib\rt. Ketika aku menulis buku ini. C:\j2sdk1. dan Macintosh. Solaris.2 dan versi 1.4. Langkah selanjutnya adalah menset environment variable PATH dan CLASSPATH. maka variabel CLASSPATH akan berbunyi seperti ini: CLASSPATH=C:\j2sdk1. C:\j2sdk1. SunOS. Menggunakan contoh di atas. import javax. Sedangkan variabel CLASSPATH akan merujuk ke library JRE.5-nya masih beta. pilih Operating System yang cocok dengan komputer kamu.jar.*.4. PATH adalah letak tool-tool J2SDK dan CLASSPATH adalah letak library dari Java Runtime Environment. instalasi J2SDK terletak di C:\j2sdk1.2\bin.2\lib\tools. apa sih fungsi CLASSPATH itu? Ingat. dst… Appendix B – Instalasi J2SDK dan Tentang Packaging 163 . Tersedia J2SDK untuk Microsoft Windows. Ikuti petunjuk cara download di sana.jar.2\jre\lib\ext\dnsns. inilah yang sering kusebut JAVA_HOME.2\jre\lib\ext\ldapsec.2\jre\lib\ext\localedata.4. Maka. jalankan installernya dan ikuti petunjuk-petunjuk instalasi.jar.2\lib\dt.4.jar. Linux.4.jar Sebenarnya.4. variabel PATH akan merujuk ke: PATH=C:\j2sdk1.jar. Byte Code Java di-interpretasikan oleh JRE.Java 2 SDK dapat kamu dapatkan dari situs resmi Java di http://java.4. Misalnya. C:\j2sdk1. misalnya: import java.4.swing.sun. CLASSPATH adalah letak class-class library yang biasa kamu panggil lewat keyword import. C:\j2sdk1.com/products/j2se.2\jre\lib\ext\sunjce_provider. C:\j2sdk1. C:\j2sdk1.awt. Semuanya bisa kamu dapatkan secara cuma-cuma alias gruatis! Setelah mendapatkan J2SDK. bahwa Java adalah bahasa yang terkompilasi sekaligus terinterpretasi.4.

Biasanya berada di drive system.4. Jika kamu ingin mereka tersimpan secara permanent. java. Kita pergi ke folder tempat source code berada dan mengkompilasinya dengan tool javac.:/usr/j2sdk1. misalnya: Windows: C:\windows> SET PATH=. atau setevn di UNIX.2/bin [galih@eliza galih]$ EXPORT CLASSPATH=.JTreeDemo akan berada di folder 164 Secangkir Kopi Java .swing.4. misalnya: javax.swing. cari bagian environment variables). klik properties. kita mesti menset lagi.2\bin C:\windows> SET CLASSPATH=.awt. kode java menggunakan package dalam penamaan class-nya. ) ada di [user_home]/. kebanyakan sih C:\ Untuk Windows NT.bat. dan XP: di System properties (klik kanan icon My Computer.Driver.Kamu bisa menset environment variable dengan perintah SET di Windows.jar Cara di atas membuat environment variable yang kita masukkan tersimpan secara sementara.swing. dsb.c:\j2sdk1.ActionListener. artinya ketika komputer direstart. simpan variabel-variabel PATH dan CLASSPATH di: Untuk Windows 9x dan ME: file autoexec. Jadi jika ada class dengan nama sama dapat dibedakan dengan adanya packaging. Class dengan nama galih.:/usr/j2sdk1.4.mysql.jdbc. 2000..c:\j2sdk1.jar Linux: [galih@eliza galih]$ EXPORT PATH=.bash-profile Cara meng-kompilasi kode Java yang berpackaging adalah seperti melakukan kompilasi biasa.2/bin/jre/lib/rt. Untuk Linux: kalau tidak salah ( Tentang Packaging Untuk memudahkan pemisahan dan tata nama. com. atau export di Linux.4. galih. Nanti akan muncul class baru di dalam folder sesuai dengan nama package-nya..JFrame.JTreeDemo.2\jre\lib\rt.

berbeda warna antara keyword dan Stringnya. sehingga bisa warna-warni.class. dan EJB. Terintegrasi dengan baik fiture seperti J2SE. kita dapat mengetahui kesalahan penulisan program tanpa melakukan kompilasi dengan javac. serta Servlet! Appendix B – Instalasi J2SDK dan Tentang Packaging 165 . J2EE. Dan kita juga cukup melakukan satu klik untuk melakukan kompilasi maupun menjalankannya. aku punya class bernama galih. Ketika kukompilasi dengan javac.inprise.JTreeDemo Nah. terbentuk file class yang berada di direktori: C:\javaku\latihan\classes\galih\swing\JTreeDemo. Memiliki code insight. IDE yang menurutku terhebat sepanjang masa! Aku memberi dia 5 jempol (tangan kanan. hal itu sangatlah tidak praktis dan ruibet buanget wis – kita tak mau dipusingkan dua kali dengan masalah kompilasi setelah energi kita dihabiskan untuk menulis program. J2ME. Cara yang praktis dan menyenangkan dalam menulis Java adalah menggunakan sebuah IDE – Integrated Development Environment – yang memiliki editor khusus Java. kita harus berada di bapaknya folder package tersebut. Misalnya. Tetapi menurutku.com). tangan kiri. Untuk menjalankannya.galih/swing/JTreeDemo.swing.JTreeDemo. dan…) untuk kehebatannya. kaki kanan. selesai! Integrated Development Environment Kita bisa menulis program Java dalam sebuah Notepad dan mengkompilasinya dengan command line. Memiliki editor yang canggih dan memudahkan kita untuk menjalankan programnya. Beberapa IDE yang kurekomendasikan antara lain: Borland JBuilder: Dari Borland (http://www. kaki kiri.swing.class Untuk menjalankannya aku harus mengarahkan current directory ke folder classes dan menjalankannya dengan java: C:\javaku\latihan\classes> java galih.

JCreator cocok untuk programmer Java yang menggunakan Java untuk aplikasi standar dan tidak memerlukan fungsi-fungsi hebat yang dimiliki JBuilder. Dibuat dari bahasa Java seperti JBuilder.com). Dia juga memiliki editor yang hebat.. Forte for Java: Tool IDE Java yang dibuat aseli oleh Sun Microsystem (http://www.JCreator: Sayang sekali JBuilder yang sakti itu memiliki kelemahan yang signifikan. ia dapat disimpan di disket dengan sebuah File Splitter. Jeruk kok minum jeruk…? 166 Secangkir Kopi Java . pakailah Forte for Java.he.he. he. Jika kamu ingin membuat aplikasi Java dengan 100% menggunakan teknologi dari Sun.. yaitu bueratnya mintak ampun.sun. JCreator mengatasinya! Dengan ukuran installer yang kurang dari 3 Mega. JBuilder 9 meminta minimal memory 256 MB agar dapat berjalan lancar..

Tujuanku semata-mata hanyalah agar kesulitan-kesulitanku ketika menyelami Java karena keterbatasan bahasa Inggris. segala saran. Karena aku tahu. cacian. File Permission dan Java Sandbox.uk. maafkan aku jika aku telah lancang menulis sebuah buku seakan-akan aku adalah pakarnya Java. Meski harus kuakui. aku juga ingin mengucapkan terima kasih kepada: Allah SWT. back to campus.co. yang selalu memberikan aku yang terbaik. Tuhan Semesta Alam. Security Java. makian. maka aku bilangnya bukan Auf Wiedersehn tetapi Au Revoir! Seperti penulis lainnya. buku ini masih banyak kelemahannya. Sekali lagi. Sampai sekarang. JSP. bagi kamu yang benci dan malas membaca buku bahasa Inggris. Servlet. Aku sebenarnya masih ingin membahas teknologi Java lebih banyak lagi. yang telah memberiku karunia tak ternilai. Au Revoir! 167 . kritik. Buku sebagai tanda bahwa aku melalui liburan panjang kali ini dengan indah cemerlang. Jadi. Tetapi… yah… liburanku telah usai.Au’ Revoir! Segala puji syukur untuk Allah SWT. yang sangat sayang padaku. aku masih belajar tentang dunia pemrograman Java. dan apapun itu akan kuterima dengan tangan terentang lebar di fox_galih@yahoo. – dan tidak ada orang yang bisa ditanyai – tidak terjadi pada kamu yang ingin mengetahui Java lebih mendalam. Tidak ada pasarnya kali ye. Aku berharap buku ini dapat memuaskan keingintahuan kamu akan bahasa Java dalam bahasa Indonesia. Mungkin lain kali aku bisa menulis lagi.. Aku masih ingin menulis tentang JApplet.? Maka dari itu. dan masih banyak lagi. akhirnya buku pertamaku ini selesai juga. tak satupun buku Java berbahasa Indonesia yang membahas Java tingkat lanjut (tingkat mahir). aku bukanlah seorang pakar dalam Java. Aku mesti kuliah lagi.

Gadis-gadis cantik yang pernah kusayangi.. Meski tak pernah membuatku mengerti apa itu cinta anak muda. pinjem sebentar… 168 Secangkir Kopi Java . bukan warna kelabu. Sori ye buat pacarnya Nafik. yang paling imut..ha. meski mereka selalu menyakitiku.ha. Arunanto. FX. dan yang tambah guendut: Nafi’ah. bahwa setiap sesuatu yang kubuat selalu kupersembahkan kepada mereka. Komputerku tersayang. Bpk. Dan last but not least.sehingga liburan panjang semester IV ini amat berwarna. dosenku BPL. namun mungkin mereka tak akan pernah tahu. yang membuatku menulis buku ini.. Mungkin kalau aku tidak mengenal Java. Maafkan aku telah merusak slot memori-mu sehingga kini kau melayaniku dengan hanya kekuatan 256 MB. adekku yang paling maniez. yang menjadi pelampiasanku di kala aku patah hati. Ide itu muncul ketika aku lagi ngelamunin dia! Ha. yang paling cantik. Eliza yang cantik. yang memperkenalkan aku dengan Java. sekarang aku sedang pusing memikirkan pointer-nya C++. yang selalu mengerti aku. namun warna yang benar-benar indah cemerlang. membuat luka di hatiku dengan pisau kecil mereka.

J. P.com/docs/books/jdcbook/index.sun.4.Deitel. New Jersey: Prentice Hall Inc.sun.Santry.html.com/developer/Books/javaprogramming/JAR/index.borland. Advanced Java 2 Platform How To Program.Deitel.com Java 2 SDK. Austin. Monica. S. 1999. Calvin and Pawlan. Palo Alto: Sun Microsystem Inc. http://java. 2003. 2003. http://www. Unspecified writer. Palo Alto: Sun Microsystem Inc.1. Daftar Pustaka 169 . Writing Advanced Applications for the Java Platform.sun.Daftar Pustaka H. Unknown Source.M. http://java. Swing Example. Palo Alto: Sun Microsystem Inc.E. JBuilder 9 Documentation. 2002.html. Standard Edition Documentation version 1.com. http://java. 2002. The Java Archive (JAR) File Format.

Sign up to vote on this title
UsefulNot useful