Masalah baru Master-detail ! TableCellRenderer!

Salah satu teman saya yaitu si echo punya masalah dan telah berhasil menyelesaikannya. Kalau gak salah masalah yang dihadapi adalah master-detail di Java Swing nah kira-kira seperti dibawah ini hasil penyelesaian masalahnya.

Masalah diatas sudah diselesaikan oleh echo, tapi kok saya menemukan masalah baru. Antara lain :

  1. Tanggal lahir masih muncul secara komplit sampai ke detik-detiknya juga, bagaimana cara memperbaiki tampilan tanggal lahir agar sesuai dengan format yang diinginkan seperti 04-April-1990.
  2. Kolom Jenis kelamin juga baru menampilkan tampilan apa adanya seperti yang ada pada Enum JenisKelamin, bagaimana cara kita agar dapat menampilkan sesuai dengan keinginan.
  3. Bagaimana kalau data dari sebuah kolom bertipe double dan merupakan data berupa uang. Standar penulisan uang di Indonesia adalah simbol  “Rp.”, pemisah ribuan “.” dan koma “,” contohnya “Rp. 90.000,00”. Sedangkan default pada Java menggunakan standar amerika yaitu simbol “$”, pemisah ribuan “,” dan koma “.”.
  4. Apabila seorang mahasiswa mempunyai data berupa foto, bagaimana cara agar JTable dapat menampilkan data foto berupa gambar bukan hanya string.

Saya berfikir sejenak……………
Nah ketemu solusinya!!

Solusi tak lain dan tak bukan adalah TableCellRenderer yaitu Kelas yang digunakan untuk merender cell pada JTable sehingga kita bisa menentukan bagaimana format data dan komponen yang akan dimunculkan. Komponen yang dirender secara default oleh JTable adalah JLabel sehingga kita hanya perlu mengatur text yang tampil pada JTable, tetapi tidak menutup kemungkinan kita untuk merender komponen lain seperti JPanel.
TableCellRenderer didaftarkan pada JTable sesuai dengan type class pada setiap column, contoh TableCellRenderer untuk Date.class.

tabelMahasiswa.setDefaultRenderer(Date.class, new DateTableCellRenderer());
Source code diatas salah satu contoh pendaftaran TableCellRenderer dengan type Date.class. Oh iya untuk memastikan type dari column-column di JTable kita harus menambahkan sedikit kode program pada TableModel.

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return String.class;
            case 1:
                return String.class;
            case 2:
                return String.class;
            case 3:
                return Date.class;
            case 4:
                return Mahasiswa.JenisKelamin.class;
            case 5:
                return Image.class;
            default:
                return null;
        }
    }

Fungsi getColumnClass(int) merupakan hasil override dari kelas AbstractTableModel seperti halnya fungsi getColumnName(int). Pada NetBeans kita cukup menekan alt+insert, pilih ‘Override Method…’ kemudian pilih fungsi yang akan di override. Cara kerja fungsi getColumnClass(int) sama seperti fungsi getColumnName(int) kita harus menentukan secara manual type-type kolom sesuai dengan urutannya (ingat dimulai dari 0 bukan 1).

package org.jasoet.swing.cellrenderer;

import java.awt.Component;
import java.text.SimpleDateFormat;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;

/**
 *
 * @author Deny Prasetyo
 */
public class DateTableCellRenderer extends DefaultTableCellRenderer {

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy");

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        JLabel component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        component.setHorizontalAlignment(SwingConstants.CENTER);
        component.setText(simpleDateFormat.format(value));

        return component;
    }
}

Source code diatas merupakan solusi untuk masalah nomor 1. Kita hanya perlu memformat data yang berupa date menggunakan kelas SimpleDateFormat. Pattern yang digunakan kali ini adalah “dd MMMM yyyy” yang akan menghasilkan format tanggal seperti “01 January 2010”, untuk pattern-pattern yang lain bisa dilihat di dokumentasi kelas SimpleDateFormat.
Hasil dari format kelas SimpleDateFormat cukup kita masukkan sebagai properti text pada komponen JLabel dan apabila perlu kita atur juga alignment agar rata tengah (Center).Oh iya untuk membuat custom TableCellRender kita hanya perlu membuat kelas turunan dari DefaultTableCellRenderer dan meng-override fungsi getTableCellRendererComponent.
Nah masalah nomor 1 sudah selesai sekarang kita lanjut ke nomor 2. Konsep untuk menyelesaikan nomor 2 hampir sama seperti pada nomor 1. Pada dasarnya Enum merupakan sebuah kelas sehingga kita hanya perlu membuat sebuah TableCellRenderer dan mendaftarkannya untuk type JenisKelamin.class.

tabelMahasiswa.setDefaultRenderer(JenisKelamin.class, new JenisKelaminTableCellRenderer());
package org.jasoet.swing.cellrenderer;

import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import khannedy.blogging.masterdetail.entity.Mahasiswa.JenisKelamin;

/**
 *
 * @author Deny Prasetyo
 */
public class JenisKelaminTableCellRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        JLabel component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        component.setHorizontalAlignment(SwingConstants.CENTER);
        JenisKelamin jk = (JenisKelamin) value;
        if (jk == JenisKelamin.LakiLaki) {
            component.setText("Laki-Laki");
        } else {
            component.setText("Perempuan");
        }
        return component;
    }
}
 

Untuk menyelesaikan masalah nomor 3 dan 4 kita harus menambahkan beberapa field pada kelas Mahasiswa dan MataKuliah karena pada program yang dibuat echo tidak menyertakan contoh field berupa double dan image.

Tambahkan 1 field berupa String dengan mana urlFoto. Field ini nanti akan berisi nama file gambar yang dimaksudkan sebagai Foto.


private String urlFoto;
 public String getUrlFoto() {
 return urlFoto;
 }

 public void setUrlFoto(String urlFoto) {
 this.urlFoto = urlFoto;
 }

Tambahkan 2 field yaitu sks dan biaya pada kelas MataKuliah, Sks bertipe Integer dan Biaya bertipe Double.  Untuk 2 field ini sudah jelas kan kegunaannya.


private int sks;
private Double biaya;

public Double getBiaya() {
return biaya;
}

public void setBiaya(Double biaya) {
this.biaya = biaya;
}

public int getSks() {
return sks;
}

public void setSks(int sks) {
this.sks = sks;
}

Dengan bertambahnya 1 field pada kelas Mahasiswa dan 2 Field pada otomatis kita diharuskan untuk mengedit TableModelMahasiswa,TableModelMataKuliah dan MahasiswaService.

TableModelMahasiswa.java


package khannedy.blogging.masterdetail.model;

import java.awt.Image;
import java.util.Date;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import khannedy.blogging.masterdetail.entity.Mahasiswa;

public class TableModelMahasiswa extends AbstractTableModel {

private List<Mahasiswa> list;

public TableModelMahasiswa(List<Mahasiswa> list) {
this.list = list;
}

public List<Mahasiswa> getList() {
return list;
}

public int getRowCount() {
return list.size();
}

public int getColumnCount() {
return 6; //Edited by Jasoet
}

@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "Nim";
case 1:
return "Nama Depan";
case 2:
return "Nama Belakang";
case 3:
return "Tanggal Lahir";
case 4:
return "Jenis Kelamin";
//Added by Jasoet [start]
case 5:
return "Foto";
//Added by Jasoet [end]
default:
return null;
}
}

public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return list.get(rowIndex).getNim();
case 1:
return list.get(rowIndex).getNamaDepan();
case 2:
return list.get(rowIndex).getNamaBelakang();
case 3:
return list.get(rowIndex).getTanggalLahir();
case 4:
return list.get(rowIndex).getJenisKelamin();
//Added by Jasoet [start]
case 5:
return list.get(rowIndex).getUrlFoto();
//Added by Jasoet [end]
default:
return null;
}
}

//Added by Jasoet [start]
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return String.class;
case 1:
return String.class;
case 2:
return String.class;
case 3:
return Date.class;
case 4:
return Mahasiswa.JenisKelamin.class;
case 5:
return Image.class;
default:
return null;
}
}
//Added by Jasoet [end]
}

TableModelMataKuliah.java


package khannedy.blogging.masterdetail.model;

import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import khannedy.blogging.masterdetail.entity.MataKuliah;

public class TableModelMataKuliah extends AbstractTableModel {

private List<MataKuliah> list = new ArrayList<MataKuliah>();

public void setList(List<MataKuliah> list) {
this.list = list;
fireTableDataChanged();
}

public int getRowCount() {
return list.size();
}

public int getColumnCount() {
return 4;//Edited by Jasoet
}

@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "Kode";
case 1:
return "Nama";
//Added by Jasoet [start]
case 2:
return "SKS";
case 3:
return "Biaya";
//Added by Jasoet [end]
default:
return null;
}
}

public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return list.get(rowIndex).getKode();
case 1:
return list.get(rowIndex).getNama();
//Added by Jasoet [start]
case 2:
return list.get(rowIndex).getSks();
case 3:
return list.get(rowIndex).getBiaya();
//Added by Jasoet [end]
default:
return null;
}
}

//Added by Jasoet [start]
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return String.class;
case 1:
return String.class;
case 2:
return Integer.class;
case 3:
return Double.class;
default:
return null;
}
}
//Added by Jasoet [end]
}

MahasiswaService.java


package khannedy.blogging.masterdetail.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import khannedy.blogging.masterdetail.entity.Mahasiswa;
import khannedy.blogging.masterdetail.entity.MataKuliah;

public class MahasiswaService {

 public List<Mahasiswa> getAllMahasiswa(Integer count) {
 List<Mahasiswa> mahasiswas = new ArrayList<Mahasiswa>();

 for (int i = 0; i < count; i++) {
 if (i % 4 == 0) {
 Mahasiswa mahasiswa = createMahasiswa("10106031", "Eko Kurniawan", "Khannedy", new Date(), Mahasiswa.JenisKelamin.LakiLaki,"p.png");
 mahasiswa.add(createMataKuliah("IF3456", "Sistem Informasi Geografis",3,90000));
 mahasiswa.add(createMataKuliah("IF3457", "Komputer Grafika",3,80000));
 mahasiswa.add(createMataKuliah("IF3458", "Rekayasa Perangkat Lunak",2,12000));
 mahasiswa.add(createMataKuliah("IF3459", "Pemrograman Berorientasi Objek",4,45000));
 mahasiswas.add(mahasiswa);
 } else if (i % 4 == 1) {
 Mahasiswa mahasiswa = createMahasiswa("10106032", "Tini", "Sumarni", new Date(), Mahasiswa.JenisKelamin.Perempuan,"7.png");
 mahasiswa.add(createMataKuliah("IF3413", "Algoritma dan Pemrograman Lanjutan",1,21000));
 mahasiswa.add(createMataKuliah("IF3489", "Kewirausahaan",3,23000));
 mahasiswa.add(createMataKuliah("IF3468", "Manajemen Proyek",4,45000));
 mahasiswa.add(createMataKuliah("IF3499", "Sistem Basis Data",3,16000));
 mahasiswas.add(mahasiswa);
 } else if (i % 4 == 2) {
 Mahasiswa mahasiswa = createMahasiswa("10106032", "Tono", "Sumarno", new Date(), Mahasiswa.JenisKelamin.LakiLaki,"8.png");
 mahasiswa.add(createMataKuliah("IF3412", "Algoritma dan Pemrograman",5,23000));
 mahasiswa.add(createMataKuliah("IF3457", "Komputer Grafika",2,40000));
 mahasiswa.add(createMataKuliah("IF3468", "Manajemen Proyek",1,50000));
 mahasiswa.add(createMataKuliah("IF3449", "Pengolahan Citra",2,23000));
 mahasiswas.add(mahasiswa);
 } else {
 Mahasiswa mahasiswa = createMahasiswa("10106022", "Rina", "Sholihat", new Date(), Mahasiswa.JenisKelamin.Perempuan,"12.png");
 mahasiswa.add(createMataKuliah("IF3412", "Algoritma dan Pemrograman",2,45000));
 mahasiswa.add(createMataKuliah("IF3489", "Kewirausahaan",3,25000));
 mahasiswa.add(createMataKuliah("IF3466", "Database Lanjut",4,40000));
 mahasiswa.add(createMataKuliah("IF3423", "Pengenalan Ilmu Komputer",2,29000));
 mahasiswas.add(mahasiswa);
 }
 }

 return mahasiswas;
 }

 protected MataKuliah createMataKuliah(String code, String name,int sks,double biaya) {
 MataKuliah mataKuliah = new MataKuliah();
 mataKuliah.setKode(code);
 mataKuliah.setNama(name);
 mataKuliah.setSks(sks);
 mataKuliah.setBiaya(biaya);
 return mataKuliah;
 }

 protected Mahasiswa createMahasiswa(String nim, String namaDepan,
 String namaBelakang, Date tanggalLahir,
 Mahasiswa.JenisKelamin jenisKelamin,String urlFoto) {

 Mahasiswa mahasiswa = new Mahasiswa();
 mahasiswa.setJenisKelamin(jenisKelamin);
 mahasiswa.setNamaBelakang(namaBelakang);
 mahasiswa.setNamaDepan(namaDepan);
 mahasiswa.setNim(nim);
 mahasiswa.setTanggalLahir(tanggalLahir);
 mahasiswa.setUrlFoto(urlFoto);
 return mahasiswa;
 }
}

Setelah itu kita perlu membuat 2 buah TableCellRenderer lagi yaitu ImageTableCellRenderer dan DoubleTableCellRenderer.

ImageTableCellRenderer.java

package org.jasoet.swing.cellrenderer;

import java.awt.Component;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;

/**
 *
 * @author Deny Prasetyo
 */
public class ImageTableCellRenderer extends DefaultTableCellRenderer {

 private String imageLocation = "/org/jasoet/swing/images/";

 @Override
 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
 if (isSelected) {
 JLabel component = new JLabel();
 URL resource = getClass().getResource(imageLocation + value);
 ImageIcon imageIcon = new ImageIcon(resource);

 component.setIcon(imageIcon);
 component.setText("");
 component.setHorizontalAlignment(SwingConstants.CENTER);
 int currentHeight = table.getRowHeight(row);
 int currentRowWidth = table.getColumnModel().getColumn(column).getPreferredWidth();

 if (currentHeight < imageIcon.getIconHeight()) {
 table.setRowHeight(row, imageIcon.getIconHeight());
 }
 if (currentRowWidth < imageIcon.getIconWidth()) {
 table.getColumnModel().getColumn(column).setPreferredWidth(imageIcon.getIconWidth());
 }

 return component;
 } else {
 JLabel component = new JLabel();

 component.setText("" + value);
 component.setHorizontalAlignment(SwingConstants.CENTER);
 table.setRowHeight(row, 16);

 return component;
 }
 }
}

DoubleCellRenderer.java


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.jasoet.swing.cellrenderer;

import java.awt.Component;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;

/**
 *
 * @author Deny Prasetyo
 */
public class DoubleCellRenderer extends DefaultTableCellRenderer {

 private DecimalFormat decimalFormat;

 public DoubleCellRenderer() {
 Locale idLocale = new Locale("id");
 DecimalFormatSymbols dfs = new DecimalFormatSymbols(idLocale);
 dfs.setCurrencySymbol("Rp. ");
 decimalFormat = new DecimalFormat("\u00A4##,###.##", dfs);
 }

 @Override
 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
 JLabel component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
 component.setHorizontalAlignment(SwingConstants.RIGHT);
 component.setText(decimalFormat.format(value));

 return component;
 }
}

Hasilnya kira-kira sperti ini.

Untuk kode program komplit  bisa di-checkout menggunakan Subversion di https://jasoet.googlecode.com/svn/tags/master-detail atau download file zipnya di sini.

    • Hendro Steven
    • Februari 22nd, 2010

    aku ketemu masalah baru : ribet😉 hehehehehe buatin genericnya aja biar bisa reuse😀

  1. @Hendro Steven
    Yoi mas abis ini akan aku buatain yang versi Generic dan support Lokalisasi* hehehe.

    *bukan lokalisasi yang itu lho

    • krissadewo
    • Februari 22nd, 2010

    Mantab…..

  2. wah materi blognya saing bersaing ma mas echo nih😀

    • nanang
    • Mei 17th, 2010

    MAs lam kenal???tanya nih gmn to buat penomoran secara otomatis diJtabel..biar saat kita masukkin data ke Jtabel maka secara otomatis nomornya akan bertambah??? mohon jawabannyaa…terima kasih

  3. wah sip jos ini..:D

    • newbie
    • November 11th, 2010

    mas mau tanya ne..
    kalo mau bikin table yang bisa di kasih action gimana ya kaya aplikasi yang pake vb gitu..
    misal ada tabel barang di kolom nama barang kita ketikkan nama brang trus dienter bisa panggil data barang yang namanya mengandung string nama yg kita input…

    ..eh satu lagi mas..??
    ko button yang udah ditruh actionperformed ga ngelakuin action pass ditekan ENTER pdhal udah diset fokus ke button
    tersebut…

    • zacknov
    • Juni 28th, 2011

    Mantap bahasa Java, kayaknya ini gudang ilmu java..

  4. kl masalahku beda lg…
    mas” ad yg bs bantu gag ??
    ak punya kasus gini,,
    dalam database ak punya table kaset column’y :
    kode_cd
    Jdl_cd
    status (0=pinjam, 1 = ada)..

    d database’y ud ada data :
    1
    transformers
    1..
    (dan data ini udah ak tampilkan lewat Jtable (kecuali column status sengaja dihilangkan) pada form kaset ) ..

    pada saat proses peminjaman otomatis kan status kaset bernilai “0” (dipinjam)..

    prtanyaanya :
    gmana cara’y mmberi warna (misalkan grey) pada row Jtable apabila status kaset pada database bernilai “1”,
    dan warna merah apabila status kaset pada database bernilai “0” ??

    nb :
    istilah’y warna row tu sbagai pemberitahuan kpada pengguna aplikasi bahwa kondisi kaset ada atau sedang di pinjam

    aku ud baca tutorial
    http://eecchhoo.wordpress.​com/2008/11/10/mengubah-wa​rna-background-jtable-agar​-warna-warni/

    tp ak bingung kl kasus’y seperti in gmana ??
    mohon bgt pencerahan’y mas…

  5. gan punyaku bertuliskan “ERROR : com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect date value: ‘Thu Oct 13 18:29:32 ICT 2011’ for column ‘tgl_lhr’ at row 1” punya solusi?

    • Muhamad Iqbal
    • Maret 4th, 2014

    master mau tanya dong maklum masih nubi..
    ane pake formated field trus ane seting manual lewat properties pada value..
    mau tanya master pada custom code kita isi apa yah ?

    contoh pada format date pada value properties kita isi “new java.util.Date()”

    maksih master😀

  1. No trackbacks yet.

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: