secangkir kopi java
JAVA 2 STANDARD EDITION

Oleh: Galih Satria

Copyright © Agustus 2004

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

view controller januari 2004 .model .

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

java database connectivity [ jdbc ] Desember 2003 .

.

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

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

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

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

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

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

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

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

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

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

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

"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

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

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

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

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

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

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

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

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

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

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

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

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

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

studi kasus jdbc – address book .

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

.

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

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

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

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

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

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

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