Bekerja dengan Swing, apalagi jika berurusan dengan tampilan data, pasti pernah menggunakan Jtable
bukan? Ada relasi yang kemarin mengalami situasi, di mana data yang harus ditampilkan ternyata sangat besar, mencapai 17 ribu buah, dan katanya, itu akan terus bertambah.
Sebenarnya sih, data itu sih tidak terlalu banyak untuk kekuatan komputer modern saat ini. Tidak akan membuat aplikasinya hang kok. Tapi, dengan data sebanyak itu, akan menimbulkan delay yang lumayan mengganggu ketika tabel data tersebut ditampilkan.
Solusinya? Upgrade ke Super Computer aja.
Hehehe, gak segitunya juga kali ya.
Setelah diperhatikan, sebenarnya tampilan data itu sama sekali tidak ada gunanya. Artinya, jarang sekali user benar benar memperhatikan dengan detail 17 ribu baris data tersebut, bahkan, kebanyakan cuma ditampilkan sebentar, puter puter mouse, pindah ke halaman lain. Atau melakukan pencarian item tertentu. Jadi, pertanyaannya, untuk apa data sebanyak itu ditampilkan sekaligus? Tapi beliau ngotot, atasan di kantor maunya begitu, mereka maunya bisa dilihat semua, meskipun pake scroll.
Okelah, kalo udah bawa bos, udah susahlah.
Ada satu teknik pengambilan data, yang dilakukan ketika dibutuhkan. Jadi data itu hanya ditampilkan ketika memang perlu ditampilkan. Dalam kasus ini, diperhatikan bahwa baris yang muncul di layar komputer sangat terbatas, anggaplah misalnya 100 baris sekali tampil, maksimum. Tentu saja, beda resolusi komputer akan beda jumlahnya. Dan ada scrollbar bukan ?
Bagaimana jika menampilkan hanya 100 baris, namun ketika user scroll mendekati akhir dari jumlah baris itu, kita ambil lagi 100 baris berikut. User scroll lagi, mendekati akhir lagi, kita ambil lagi. Dan seterusnya, hingga seluruh data terambil. ini namanya Lazy Loading. Akan jauh lebih cepat memproses 100 data dibandingkan 17 ribu, bukan ?
Berikut saya berikan contohnya, tentu saja, data di contoh ini adalah auto-generated, jika Anda memahami kode sumber di bawah, Anda akan mudah mengubah sumber datanya, misalnya diambil dari database.
File Jar yang dapat dijalankan bisa didownload disini. Mungkin bisa digunakan untuk menguji roda mouse ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | package whatever; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; /** * Created by konglie on 3/14/16. */ public class LazyLoad extends JFrame { public static void main(String[] args){ new LazyLoad(); } int currentPage = 0, loadPerPage = 50; boolean isLoading = false; JPanel body, headerPanel; JTable theTable; DefaultTableModel dtm; JScrollPane scrollPane; JTextField inputLimit; public LazyLoad(){ setTitle("JTable Lazy Loading"); setResizable(false); setPreferredSize(new Dimension(640, 480)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); body = new JPanel(new BorderLayout()); inputLimit = new JTextField("1000000"); inputLimit.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { dtm.setRowCount(0); currentPage = 0; loadData(); } }); headerPanel = new JPanel(new BorderLayout()); headerPanel.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15)); headerPanel.add(new JLabel("Limit Data"), BorderLayout.WEST); headerPanel.add(inputLimit, BorderLayout.CENTER); body.add(headerPanel, BorderLayout.NORTH); dtm = new DefaultTableModel(new Object[][]{}, new String[]{"Kolom 1", "Kolom 2", "Kolom 3"}){ @Override public boolean isCellEditable(int r, int c){ return false; } }; theTable = new JTable(dtm); scrollPane = new JScrollPane(theTable); body.add(scrollPane, BorderLayout.CENTER); getContentPane().add(body, BorderLayout.CENTER); pack(); setLocationRelativeTo(null); setVisible(true); loadData(); setupLazyLoad(); } void loadData(){ if(isLoading){ return; } int limit = 0; try{ limit = Integer.parseInt(inputLimit.getText()); if(theTable.getRowCount() >= limit){ return; } } catch (Exception e){ } isLoading = true; int p = (int) Math.ceil(Math.log10(limit)); if(p < 1){ p = 1; } for(int i = (currentPage++ * loadPerPage); i < (loadPerPage * currentPage); i++){ dtm.addRow(new Object[]{ String.format("Baris %0"+p+"d, kolom 1", i), String.format("Baris %0"+p+"d, kolom 2", i), String.format("Baris %0"+p+"d, kolom 3", i) }); } isLoading = false; } void setupLazyLoad(){ final JScrollBar scrollBar = scrollPane.getVerticalScrollBar(); // tinggi setiap baris final int rh = theTable.getRowHeight(); scrollBar.getModel().addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent event) { BoundedRangeModel model = (BoundedRangeModel) event.getSource(); int extent = model.getExtent(); int maximum = model.getMaximum(); int value = model.getValue() + extent; int diff = maximum - value; // jumlah baris tersisa sebelum kita mengambil data baru int rowBeforeLoad = 15; if(Math.floor(diff - value) <= (rowBeforeLoad * rh)){ SwingUtilities.invokeLater(new Runnable() { @Override public void run() { loadData(); } }); } } }); } } |
Kuncinya adalah, seperti pada teknik paging, mengambil data pada offset tertentu. Misalnya, kita tentukan sekali pengambilan data adalah 10 buah, maka pengambilan pertama adalah 1 – 10, pengambilan kedua adalah 11 – 20, dan seterusnya.
Demikian, semoga berguna untuk kita semua.