secangkir kopi java
JAVA 2 STANDARD EDITION

Oleh: Galih Satria

Copyright © Agustus 2004

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

model .view controller januari 2004 .

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

java database connectivity [ jdbc ] Desember 2003 .

.

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

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

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

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

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

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

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

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

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

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

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

"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

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

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

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

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

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

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

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

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

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

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

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

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

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

studi kasus jdbc – address book .

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

.

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

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

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

Jika kamu ingin membuat aplikasi Java dengan 100% menggunakan teknologi dari Sun. Dia juga memiliki editor yang hebat. 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. Jeruk kok minum jeruk…? 166 Secangkir Kopi Java . JCreator mengatasinya! Dengan ukuran installer yang kurang dari 3 Mega.he. ia dapat disimpan di disket dengan sebuah File Splitter. pakailah Forte for Java. yaitu bueratnya mintak ampun.. he. JBuilder 9 meminta minimal memory 256 MB agar dapat berjalan lancar.sun.JCreator: Sayang sekali JBuilder yang sakti itu memiliki kelemahan yang signifikan. Dibuat dari bahasa Java seperti JBuilder.com).he..

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

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

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

Sign up to vote on this title
UsefulNot useful