secangkir kopi java
JAVA 2 STANDARD EDITION

Oleh: Galih Satria

Copyright © Agustus 2004

The author makes no warranty of any kind. with regrad to these programs or to the documentation contained in this book. Not for commercial use. scolarship. You may only use this book for private study. . or research.All rights reserved. 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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

view controller januari 2004 .model .

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

DefaultTreeModel mengandle seluruh tree.Ketika DefaultMutableTreeNode merepresentasikan sebuah node.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. 62 Secangkir Kopi Java . pertama kamu harus membuat root instans dari tree. TreeModel tidak secara langsung mengatur dan memodifikasi data. Data dari tree diatur oleh class DefaultMutableTreeNode. juga untuk memasang customized icon untuk setiap nodenya. DefaultMutableTreeNode kemudian membuat untuk instans merepresentasikan DefaultTreeModel yang sesuai dengan root. Gambar 2. Class TreeSelectionModel menghandle pemilihan node tree. misalnya. Dan class TreePath adalah class pendukung yang merepresentasikan suatu node dalam suatu path.4. Untuk membuat sebuah tree model. Class DefaultTreeCellRenderer menyediakan mekanisme untuk merender node tree sebagai sebuah label. Tidak seperti ListModel dan TableModel.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

java database connectivity [ jdbc ] Desember 2003 .

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

studi kasus jdbc – address book .

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

.

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful