secangkir kopi java
JAVA 2 STANDARD EDITION

Oleh: Galih Satria

Copyright © Agustus 2004

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Kotak input yang sangat dinamis dan fleksibel. Aku ingat.NO_OPTION ) { //. Akan muncul dialog seperti ini: Bentuk Kedua: 20 Secangkir Kopi Java . 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. Bentuk Pertama: JOptionPane..else if ( result == JOptionPane.showInputDialog(null. aku selalu memakai fungsi getche() dalam blok do-while untuk mendapatkan masukan dari user.showInputDialog ( Component parentComponent. jika no ngapain. Kurasa. "Berapa umurmu?"). ketika Aku memakai bahasa C semester I dan II kemarin. hanya Swing yang memiliki kotak input serame ini. taruh di sini } else { // yang ini mah pasti cancel } Listing 1. Object message ). Jika aku menulis JOptionPane. Bentuk yang paling sederhana.

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

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

view controller januari 2004 .model .

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

editingColumn: Kolom dari cell yang sedang diedit. Oke. editingRow: Baris dari cell yang sedang diedit. Sebelum kita menginjak ke bagian coding. mari kita test beberapa properti dari JTable dalam sebuah tampilan sederhana.AUTO_RESIZE_ALL_COLUMNS cellSelectionEnabled: Bertipe boolean. Nilai defaultnya adalah true. columnSelectionAllowed: Nilai boolean yang menunjukkan apakah kolom JTable boleh dipilih atau tidak. Yuk… Model View Controller 39 . Semuanya bisa dilihat di dokumentasi dari JTable. Masih segudang lagi properti dari JTable yang bisa kita ubah-ubah sesuai kebutuhan kita. 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.AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable. Object[] columnNames ). public JTable ( Object[][] rowData. Berikut ini adalah kemungkinan bagaimana kolom JTable dimanipulasi: JTable. aku perlu memperkenalkan properti yang dimiliki oleh JTable. kamu tidak bisa seenak udel mengubahnya. Mereka adalah: autoCreateColumnsFromModel: Bertipe boolean.AUTO_RESIZE_NEXT_COLUMN JTable. Tetapi untuk baris.AUTO_RESIZE_LAST_COLUMN JTable. Gunanya untuk menunjukkan apakah kolom-kolom dibuat dari table model. Menunjukkan apakah boleh kita memilih suatu cell secara individual.

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

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

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

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

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

menentukan cell renderer dan cell editor. Class ini tidak dapat dibuat secara langsung ( instantiated ). 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. Class ini digunakan untuk memanipulasi suatu kolom tertentu secara individual pada JTable. tetapi kita bisa mendapatkan objek ini dari method getColumn ( int index ) pada TableColumnModel atau method getColumn ( Object identifier ) 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 .public void moveColumn(int fromIndex. Beberapa method di bawah ini adalah milik class TableColumn untuk mengatur panjang kolom. dan header renderer.

event.*.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 JButton btnAddCol = new JButton ( "Add Column" ). Listing 2.swing.swing. Okay? Let’s go! package galih. import javax. kita dapat menambah dan menghapus baik baris ataupun kolom. import javax. import java. 46 Secangkir Kopi Java .*.awt. yaitu TableModel dan ColumnModel. private JButton btnAddRow = new JButton ( "Add Row" ). Siapkan dirimu untuk membaca kode gila! Tapi itu akan percum tak bergun jika kamu tidak mencobanya sendiri. private DefaultTableModel tableModel.*. import java. private JButton btnRemoveCol = new JButton ( "Remove Column" ). private JButton btnRemoveRow = new JButton ( "Remove Row" ).table.swing.6 – Dengan TableModel.awt. Di sini diperkenalkan dua model.0" ). public class TableDemo2 extends JFrame { //instans private JTable table. //konstruktor public TableDemo2() { super ( "Table Demo ver 2.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Class ini mengatur icon-icon untuk node leaf. Tree Cell Renderer dan Tree Cell Editor Seperti halnya komponen Swing tingkat tinggi lainnya. yang diimplementasikan oleh class DefaultTreeCellRenderer. Dia juga mengatur warna foreground dan background dari setiap node. Interface TreeCellRenderer mendefinisikan bagaimana sel dirender. Sampai sekarangpun kabut yang menutupi JTree di depan mataku belum sepenuhnya terkuak. BBS-ku memakai Java Applet dan koneksi databasenya memakai MySQL JDBC-Native-Connection.Gambar 2. 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 ). JTree juga memiliki cell renderer. node yang tertutup ( collapsed ).7 – Hasil dari first run kita terhadap JTree Aku mengenal JTree untuk pertama kalinya sekitar bulan Januari 2004. 68 Secangkir Kopi Java . dan node yang terbuka ( expanded ).

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

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

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

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

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

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

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

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

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

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

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

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

java database connectivity [ jdbc ] Desember 2003 .

.

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

arti huruf besar adalah keyword. dan yang berada di dalam tanda [ ] boleh disertakan atau tidak sesuai dengan kebutuhan.1 – Relationship yang dipakai dalam database AkademikPIKTI 84 Secangkir Kopi Java . Gambar 3. aku akan menggunakan database AkademikPIKTI. yang harus disertakan jika kita membutuhkan pengolahan data.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. yang kudapat dari kuliah Basis Data-nya Pak Imam K semester III kemarin. Sebagai contoh. yang berhuruf kecil merupakan isian yang bisa diubah sesuai dengan kebutuhan kita.

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

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

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> [. • MAX ( kolom ) untuk mendapatkan nilai tertinggi pada suatu kolom. • MIN ( kolom ) untuk mendapatkan nilai terendah pada suatu kolom. • SUM ( kolom ) untuk mendapatkan jumlah keseluruhan dari suatu kolom. COUNT(*) FROM anggota GROUP BY JK Untuk menampilkan rata-rata harga koleksi per kode penerbit SELECT idPenerbit. Contoh: Untuk menampilkan jumlah anggota perjenis kelamin: SELECT JK. AVG(harga) FROM koleksi GROUP BY idPenerbit Java Database Connectivity [ JDBC ] 87 . <kolom 2> ] Klausa ini digunakan untuk mengelompokkan fungsi-fungsi agregate. • AVG ( kolom ) untuk mendapatkan nilai rata-rata pada suatu kolom. Fungsi-fungsi tersebut yaitu: • COUNT ( * ) untuk mendapatkan jumlah baris.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. Proses tersebut akan mengolah nilai sebuah field atau lebih mulai baris pertama sampai seluruh baris.

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

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

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

nipdosen 09:\> SELECT mhs.nipwali=dosen.kodejam=jam.kodekul=matakul.doesn.nilai<56 14:\> SELECT distinct nama.nama FROM mahasiswa WHERE nrp NOT IN (SELECT distinct nrp FROM pesertakul WHERE (nihuruf='D' OR nihuruh='E')) 12:\> SELECT distinct dosen.nama.namakul='Pemrograman Database' 10:\> SELECT * FROM dosen WHERE nip NOT IN (SELECT distinct nipwali from mahasiswa) 11:\> SELECT nrp.mahasiswa.nrp.matakul WHERE mahasiswa.nama FROM mahasiswa.kodekul AND dosen.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 .kodehari=hari.kodekul AND pesertakul.pesertakul WHERE mahasiswa.sesikuliah.nip AND mahasisea.pesertakul.nrp=pesertakul.kelas='ca' AND matakul.kodehari AND sesikuliah.nama.nrp AND pesertakul.nip=sesikuliah.mahasiswa.nrp=pesertakul.namakul.kodekul=pesertakul.pesertakul.nrp=pesertakul.kodekul AND matakul.nrp AND pesertakul.kodekul=matakul.nrp FROM dosen.nilai FROM mahasiswa.pesertakul.nrp AND pesertakul.matakul WHERE mhs.nihuruf='E' 13:\> SELECT matakul.kodejam AND sesikuliah.

kelas. mahasiswa. Java Database Connectivity First Run! Setelah kita membahas habis SQL dengan begitu detail.nrp AND pesertakul.jeniskel.nilai.alamat AS alamat FROM mahasiswa WHERE mahasiswa.17:\> SELECT mahasiswa.nrp GROUP BY pesertakul.nilai. rasanya tidak etis jika aku kembali membahas konsep JDBC.nrp=pesertakul.dosen.jeniskel 20:\> SELECT mahasiswa.maasiswa.alamat like '*Sidoarjo*' UNION ALL SELECT dosen. aku sudah bilang “sori”. MAX(pesertakul.nilai).alamat FROM dosen WHERE dosen.kul) FROM matakul.nama. mahasiswa. MIN(pesertakul. MAX(pesertakul. Bisa-bisa aku nanti 92 Secangkir Kopi Java . ii.mahasiswa WHERE mahasiswa.AVG(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.nilai WHERE mahasiswa.sks) FROM mahasiswa. AVG(pesertakul.nama AS nama. MIN(pesertakul.kul).kodekul=matakul.nilai.matakul. Jadi kalau ada sedikit error.kelas.nrp=pesertakul.nilaikul.kode 18:\> SELECT matakul.namakul 19:\> SELECT pesertakul.kodekul=matakul.nilai).SUM(nilai.nrp.kul).kodekul AND pesertakul.pesertakul WHERE pesertakul.nama.nihuruf=nilai.s ks)/SUM(matakul.kodekul GROUP BY matakul.pesertakul.nilai) FROM pesertakul.nangka*matakul.

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

"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

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

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

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

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

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

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

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

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

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

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

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

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

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

studi kasus jdbc – address book .

.

saat menikmatinya.1 – Relasi antar entitas pada database address book. instalasi database. Database Design Untuk database besar hingga lebih dari 10 tabel dengan relasi yang rumit. Gambar 4. 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. Aku akan memulainya dari mendesain database. biasanya aku memakai Sybase Power Designer 9 untuk mendesainnya. Relasi yang digambarkan dengan cara di atas disebut Relasi Cakar Ayam. aku tidak membahas itu. hingga penulisan program dan terakhir. Tetapi sekali lagi karena ini bukan buku tentang database. Buku alamat sangat tepat untuk dijadikan studi kasus karena tidak terlalu rumit dan dapat mencangkup semua teori dasar JDBC. pembuatan tabel dengan DDL.Kali ini kita akan mengimplementasikan semua teori-teori tentang JDBC ke dalam sebuah aplikasi buku alamat. i.

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

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

Tabel Email: create table if not exists EMAIL ( ORANG_ID int not null. MOBILE varchar(20). primary key (ORANG_ID. 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 ). EMAIL_ID) ). ALAMAT_ID) ). TELP_ID) ). Tabel Telp: create table if not exists TELP ( ORANG_ID int not null. EMAIL_ID int not null. EMAIL_ADDRESS varchar(50). Index Constraint pada tabel Orang dengan Telp: create index ORANG_TELP_FK on TELP ( ORANG_ID 116 Secangkir Kopi Java . RUMAH varchar(15). ALAMAT_ID int not null. primary key (ORANG_ID.Tabel Orang_Alamat ( Tabel perantara relasi many-to-many ): create table if not exists ORANG_ALAMAT ( ORANG_ID int not null. TELP_ID int not null. primary key (ORANG_ID.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

.

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful