NestedScrollView VS ScrollView

Ceritanya, beberapa hari terakhir saya main2 ama layar yang bisa di-scroll di Android. Berbekal pengalaman training dari beberapa tahun lalu, saya tau musti pakai Scroll View. Dan kebetulan, pas kemarin ngecek dokumentasi dari scroll view, saya menemui kenyataan bahwa ada yang namanya NestedScrollView. Saya ga tau ini adanya sejak kapan, tapi ternyata yang disarankan justru menggunakan NestedScrollView, dan bukan ScrollView. Menurut stackoverflow, pebedaan mendasarnya adalah:

  1. NestedScrollView digunakan jika ada view yang harus di-scroll (digulir) di dalam view lain yang juga harus di-scroll.
  2. NestedScrollView compatible dengan CoordinatorLayout.

Perbedaan mendasar bisa dilihat dari hal di atas, tapi secara behaviour pun, ternyata ScrollView sama NestedScrollView punya sifatnya masing-masing. Saya ga bisa klasifikasikan ini sebagai kelebihan/kekurangan, jadi kamu bisa nilai sendiri nantinya.

Jadi… perbedaan behaviour yang pertama apa? Jawabannya… ScrollView akan nge-scroll balik ke focus edit text yang terpilih. Mungkin kamu bingung, jadi di sini akan saya perlihatkan screen layar saya dengan aplikasi JustJava dari Udacity.com pelajaran 3B (kamu musti sign-in dulu buat liat materinya).

ScrollView – Screen Scroll Back

Kalau kamu lihat gif di atas, kamu mungkin bisa tau kalau tiap kali button di-klik, maka layar kembali ke-scroll ke atas. Hal ini terjadi karena di layar, ada edit text yang sedang dalam kondisi “focus” (bisa dilihat dari cursor yang berkedip). ScrollView punya kecendrungan buat nampilin edit text yang focus itu. Kalau edit text yang lagi focus ini di dekat tombol, mungkin ga bakal keliatan pengaruhnya di layar. Tapi kalau udah pakai contoh kasus seperti di atas, edi text di paling atas layar, sedangkan button di paling bawah, ini bikin frustasi. Oh iya, untuk informasi. Hal ini ga akan terjadi kalau kamu pakai NestedScrollView. Untuk mengatasi hal di atas dari ScrollView (ceritanya kamu tetap harus pakai scroll view), maka kamu perlu menambahkan kode untuk menambahkan focus langsung di scroll view-nya. Caranya:

ScrollView view = (ScrollView)findViewById(R.id.scrollView);
view.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
view.setFocusable(true);
view.setFocusableInTouchMode(true);
view.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        v.requestFocusFromTouch();
        return false;
    }
});

Kode di atas, saya ga bisa jelasin lebih banyak. Jadi bisa dilihat sendiri langsung di sumbernya ya. Yap! Kodenya pakai Java. Kalau kotlin, belum tau.. belum move on eung. Segera deh.

Oke… itu behaviour dari ScrollView yang ga dimiliki oleh NestedScrollView. Sekarang, sebaliknya. Hal yang dimiliki NestedScrollView. Sifatnya, NestedScrollView gak akan bisa digulir kalau keyboard lagi dalam mode open. Hmmm… mungkin baiknya kamu lihat dulu kondisinya kayak gimana dari gambar di bawah ini.

Kondisi di atas merupakan kondisi normal dari ScrollView. Pas waktu keyboard lagi dalam kondisi terbuka, layar bisa di-scroll. Tapi, kondisi di atas ga akan bisa kamu temui di NestedScrollView. Bisa kamu cobain deh. Pas keyboard nutupin layar, kamu cuma bisa nge-scroll si layarnya sampai jarak tertentu yang udah kamu atur di layar. Intinya, kalau dari awal, layarnya emang udah tampil sepenuhnya di layar, layar ga akan nge-scroll. Walaupun ada view yang ketutup keyboard. Solusi dari hal ini, bisa kamu lihat dari pertanyaan di stackoverflow ini. Tambahkan android:windowSoftInputMode=”adjustResize” di manifest kamu untuk bagian activity.

<activity android:name="YourActivity" 
          android:windowSoftInputMode="adjustResize" />

Okeh… begitulah.. padahal cuma nulisin hal sepele yah, tapi jadi panjang banget gini. Tapi… Ya sudah lhah yah… Selamat bermain-main dengan view yang bisa digulir… btw, untuk yang mau bermain-main sama coordinator layout dan nested scrollview, bisa lihat link berikut. Keren banget lhoh.

Advertisements

Generic Types

Di tulisan sekarang, kita bakal bahas dikit tentang Generic Types. Apa itu generic types?! Inti dari generic types itu… sebuah tipe data yang dapat dimasukin nilai apapun. Bingung?! Baiklah… kita mulai dari konsep variabel.

Bayangkan sekarang kamu punya variabel di kode kamu masing-masing. Gambaran dari variabel adalah sebuah kotak yang memiliki kesepatakan terhadap “apa yang disimpan” dalam kotak tersebut, dan juga “jenis yang disimpan”. Contohnya, kamu punya kotak untuk menyimpan jenis-jenis sepatu, maka hal yang harus kamu simpan adalah sepatu. Hal yang kamu simpan bisa sepatu olahraga, sepatu high heel buat ke pesta, atau bahkan sepatu barbie kamu… yang penting, isinya sepatu. Akan salah besar kalau kamu simpan koleksi tas kamu dalam kotak yang dimaksudkan untuk menyimpan sepatu.

Itu konsep variabel… sekarang, bayangkan, ketika ada seseorang yang bakal menggunakan kotak tersebut. Pastinya, orang itu mau menyimpan sesuatu. Tapi… bukan sepatu lah yang mau ia simpan. Dia butuh kotak untuk menyimpan bundle-an revisi TA dari dosen pembimbing-nya. Efeknya, kotak sepatu yang tersedia, udah ga berguna lagi. Dia harus membuat kotak baru untuk menyimpan revisian2 itu. Ga efektif kan?! Harus bikin dari awal, padahal kotak sepatu masih bisa nutup lhah buat nyimpen dokumen semacam revisian TA dengan segala coretan di dalamnya.

Dan di sinilah Generic Types bekerja dengan caranya… memastikan bahwa sebuah variabel dapat menampung nilai dengan fleksibel.

Implementasi generic types yang paling gampang dilihat yaitu di penggunaan Collections dari bahasa pemrograman Java. Contoh paling gampang, di Array List. Pada saat menggunakan array list, kamu bisa menambahkan berbagai elemen dengan tipe data yang berbeda.

import java.util.ArrayList;

public class TipeUmum {
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add("hai, ini blog");
al.add("arby");
al.add(3);
System.out.println(al);
}
}
//hasil eksekusi: [hai, ini blog, arby, 3]

Lihat contoh di atas kan… Di array list bernama al, kita menambahkan 2 data dengan 2 objek yang berbeda. Tipe berupa string, dan tipe berupa angka (integer). Artinya, untuk implementasi kode array list, programmer-nya pakai tipe generic untuk mengkodekan sifat-sifat dari si list. Dan tipe ini fleksibel banget. Karena selain memberikan kemudahan, tipe ini juga bisa dibuat strict. Contohnya:

import java.util.ArrayList;

public class TipeUmum {
public static void main(String[] args) {
ArrayList<Integer> al = new ArrayList();
al.add("hai, ini blog");
al.add(" arby");
al.add(3);
System.out.println(al);
}
}

//kode di atas error, tidak dapat dikompilasi
//baris yang dicoret: baris penyebab error

Kode di atas, itu ga jauh beda dari sebelumnya. Perbedaannya, ada pada penulisan ArrayList<Integer>. Hal ini ga dipunya oleh kode yang sebelumnya. Dan begitulah cara untuk membuat array list strict dalam penggunaannya. Tentang hal ini, ada terkait dengan type erasure yang dilakukan oleh java compiler.. tapi ga usah kita bahas lhah yang itu ya.

Balik lagi ke inti tulisan kita, ArrayList di atas adalah contoh penggunaan tipe umum atau Generic Types. Dan sekarang, seandainya kita akan membuat sebuah implementasi dari generic types, gimana caranya?! Anggap kita mau membuat sebuah struktur data “circular linked list” dengan sifatnya sendiri, tapi data yang diberikan bisa beda-beda… untuk hal ini, kita butuh generic.

Implementasi generic itu dasarnya gampang banget, kamu cuma perlu mengganti setiap tipe data dari variabel yang kamu tuliskan menjadi sebuah huruf kapital. Contoh, kamu punya variabel “int data”, tinggal ganti jadi “T data” atau “D data”. Setelahnya, tambahkan huruf capital tersebut di dekat nama class, diapit dengan diamond. Contohnya, kalau tadi kamu ganti tipenya jadi T, dan ini ada di kelas bernama Box, maka tuliskan “Box<T>“. Hurufnya bisa apapun, yang penting kapital. Iya, itu aja cukup. Cuma, ada kesepakatan dalam konvensi developer, untuk penggunaan huruf kapital, harus mewakili hal-hal berikut:

  1. Untuk mewakili elemen, tuliskan E;
  2. Untuk mewakili kunci elemen (key), tuliskan K;
  3. Untuk mewakili nomor (number), tuliskan N;
  4. Untuk mewakili tipe tertentu (type), tuliskan T;
  5. Untuk mewakili nilai tertentu (value), tuliskan V;
  6. Untuk mewakili parameter 2, 3, 4, dst, tuliskan S, U, V, dst.

Tapi lagi-lagi… hal di atas cuma kesepakatan yah… enggak wajib. Sekarang, kodenya gimana?! Untuk mencoba belajar melihat sifat generic, kita butuh perbandingan antara kode non-generic-types dengan yang generic-types. Dan ini kode yang non-generic-types:

public class Kotak {
    private int barang;

    public void set(int barang) { 
        this.barang = barang; 
    }
    public int get() { 
        return barang; 
    }
}

Untuk menggunakan class di atas, kode main yang mungkin dibuat adalah

public static void main(String[] args) {
Kotak k1 = new Kotak();
k1.set(5);

Kotak k2 = new Kotak();
k2.set(10);
}

Bandingkan dengan penulisan kode dari generic types dari kotak di atas:

public class KotakG<T> {
    private T barang;

    public void set(T barang) {
        this.barang = barang;
    }
    public T get() {
        return barang;
    }
}

Untuk menggunakan class KotakG di atas, kode main yang mungkin dituliskan adalah:

public static void main(String[] args) {
KotakG k1 = new KotakG();
k1.set(5);

KotakG k2 = new KotakG();
k2.set("Revisi TA");
}

Lihat kan yah… di sini, kamu dapat memasukkan 2 tipe data yang berbeda dalam objek yang dibentuk dari class yang sama. Hal ini ga akan kamu bisa lakukan di class Kotak (yang tidak menggunakan konsep generic).

Kode lengkapnya untuk yang KotakG gini:

public class KotakG<T> {
    private T barang;

    public void set(T barang) {
        this.barang = barang;
    }
    public T get() {
        return barang;
    }

    public static void main(String[] args) {
        KotakG k1 = new KotakG();
        k1.set(5);
        System.out.println("Isi kotak k1: "+k1.get());

        KotakG k2 = new KotakG();
        k2.set("Revisi TA");
        System.out.println("Isi kotak k2: "+k2.get());
    }
}

Hasil akhirnya:

Isi kotak k1: 5
Isi kotak k2: Revisi TA

Daaaan.. begitulah. Generic Types ini banyak dibahas kalau udah ngebahas mata kuliah struktur data pakai bahasa Java. Karena, di mata kuliah itu, kita bakal bikin linked list, doubly linked list, circular linked list, tree, graph, dll, dsb dengan data yang disimpan bersifat fleksibel. Bahkan bisa bertipe objek.

FYI, generic types yang kita bahas ini sebenarnya cetek yah… yaaaa, khas nya tulisan blog balita lhah.. kamu bisa lihat berbagai hal lain di sumber-sumber yang saya cantumkan di bawah ini. Dan sekarang, sekian tulisan tentang generic types.. happy learning.

Sumber:

https://docs.oracle.com/javase/tutorial/java/generics/index.htm

https://www.tutorialspoint.com/java/java_generics.htm

https://docs.oracle.com/javase/tutorial/extra/generics/index.html

Bubble Sort Part 3: Comb Sort

Postingan lanjutan, sekaligus yang terakhir dari seri bubble sort adalah comb sort. Comb sort merupakan perbaikan yang dibuat para ahli untuk mengatasi kondisi rabbit & turtle yang ada di bubble sort. Cara mengatasinya seperti apa?! Caranya adalah membandingkan 2 nilai elemen dari daftar yang tidak bersebelahan. Ada faktor jarak yang berpengaruh atas nilai apa yang dibandingkan dengan nilai yang mana.

Ilustrasinya, ketika kamu punya 4 nilai: a, b, c, d. Jika kamu mengurutkan menggunakan bubble sort, pasti urutannya adalah

  1. Bandingkan a dan b
  2. Bandingkan b dan c
  3. Bandingkan c dan d

Pasti selalu gitu, sedangkan kalau kamu punya comb sort, kamu bisa membandingkan dengan jarak. Contohnya, membandingkan elemen dengan jarak bernilai 2: maka elemen yang dibandingkan adalah a dengan c; b dengan d.. dan kalau sudah mencapai akhir perbandingan, hitung lagi jarak baru. Nilai jarak ini disebut sebagai gap value. Dan untuk menghitung gap value yang baru, dikenal adanya gap factor. Cara menentukan gap tersebut dilihat pada rumus berikut:

gap_value = gap_value/shrink_factor(k)

gap_value awal = jumlah elemen di list
shrink_factor(k) bisa bernilai berapapun.
dari penelitian sebelumnya, didapat efektif k = 1.3
penelitian tersebut menggunakan 200.000 random list

Satu hal yang harus kamu garisbawahi dan menjadi perhatian adalah, kondisi berhenti dari perulangan ini. Kondisinya adalah tidak ada lagi swapped. Hal ini sama seperti bubble sort. Akan tetapi karena nilai elemen ditukar dalam jarak tertentu, bisa jadi dalam jarak tersebut nilainya memang tidak usah di-swapped lagi sampai elemen akhir yang diperbandingkan, dan kondisi ini bisa menyebabkan perulangan terhenti, sedangkan list masih belum terurut. Sehingga, dibutuhkan satu pengkondisian lagi (selain swapped) untuk menyebabkan algoritma berhenti… yaitu gap value bernilai 1.

Berdasarkan keterangan di atas, kita coba urutkan daftar yang mempunyai kondisi turtle, yaitu: 2 4 7 9 1. Daftar nilai ini sama dengan contoh dari turtle di tulisan sebelumnya. Jadi nanti bisa kita bandingkan. Dan.. beginilah langkah pengurutannya:

Kondisi awal: 2 4 7 9 1
Gap value awal: 5
Kondisi akhir: daftar terurut menaik

First Pass
gap value = 5/1.3 = 3.8 --> 3
2 4 7 9 1 --> 2 4 7 9 1 (swapped tidak terjadi)
2 4 7 9 1 --> 2 1 7 9 4 (swapped terjadi)

Second Pass
gap value = 3/1.3 = 2.3 --> 2
2 1 7 9 4 --> 2 1 7 9 4 (swapped tidak terjadi)
2 1 7 9 4 --> 2 1 7 9 4 (swapped tidak terjadi)
2 1 7 9 4 --> 2 1 4 9 7 (swapped terjadi)

Third Pass
gap value = 2/1.3 = 1.5 --> 1
2 1 4 9 7 --> 1 2 4 9 7 (swapped terjadi)
1 2 4 9 7 --> 1 2 4 9 7 (swapped tidak terjadi)
1 2 4 9 7 --> 1 2 4 9 7 (swapped tidak terjadi)
1 2 4 9 7 --> 1 2 4 7 9 (swapped terjadi)

Fourth Pass
gap value = 1/1.3 = 0.76 --> 1
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)

Algoritma berhenti. Swapped tidak terjadi, gap = 1;
Kondisi akhir: daftar terurut menaik.

Lihat kan?! Lumayan ada perbedaan. Pas di kondisi turtle dengan bubble sort, pass yang harus dilakukan sejumlah 5, sedangkan di comb sort, cukup 4 pass sajah. Sekarang, mungkin kamu bertanya2… kodenya gimana?! Yah, sebenernya kamu cuma butuh lihat sumber yang ada di bawah tulisan ini aja. Tapi berhubung yang nulis blog ini baik, sooo… here is the code

import java.util.Random;

public class Comb_Sort {
    public int[] randomArray(int jumlah) {
        int[] arr = new int[jumlah];
        Random r = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = r.nextInt(100);
        }
        return arr;
    }
    public void tampilArray(int[] arr){
        for (int i:arr) {
            System.out.print(i+" ");
        }
    }
    public int[] urut(int[] arr)
    {
        int n = arr.length;

        // inisialisasi gap value
        int gap = n;

        boolean swapped = true;

        // lakukan perulangan
        // dan bandingkan nilai seperti bubble sort
        while (gap != 1 || swapped)
        {
            // menghitung gap
            // gap = nilai gap sebelumnya / 1.3
            gap = (gap*10)/13;
            if (gap < 1)
                gap = 1;

            swapped = false;

            // bandingkan seperti bubble
            for (int i=0; i<n-gap; i++)
            {
                if (arr[i] > arr[i+gap])
                {
                    int temp = arr[i];
                    arr[i] = arr[i+gap];
                    arr[i+gap] = temp;

                    swapped = true;
                }
            }
        }
        return arr;
    }

    public static void main(String[] args) {
        Comb_Sort nc = new Comb_Sort();
        int[] array = nc.randomArray(6);
        System.out.println("Array: ");
        nc.tampilArray(array);
        System.out.println("\n\nArray Terurut: ");
        int[] arrayUrut = nc.urut(array);
        nc.tampilArray(arrayUrut);
    }
}

Untuk hasil akhirnya kayak gini:

Begitulah… semoga tulisan ini membantu kamu yang lagi bingung sama bubble sort dan turunannya. Happy learning…

Sumber:
https://en.wikipedia.org/wiki/Comb_sort
https://www.tutorialspoint.com/Comb-Sort
https://www.geeksforgeeks.org/comb-sort/

Bubble Sort Part 2: Turtle & Rabbit

Dari posting sebelumnya, kita udah tau ada yang namanya bubble sort, bahkan udah ada program yang bisa di-run segala. Sekarang, kita bakal bahas tentang 2 hal di bubble sort yang menjadi pemikiran para ahli di bidang algoritma pengurutan. 2 hal tersebut yaitu rabbit dan turtle. Apakah kedua hal itu?

Rabbit adalah nilai tinggi yang ada di ujung daftar (sebelah kiri) dari daftar nilai yang akan diurutkan secara menaik. Sedangkan turtle adalah sebaliknya, nilai rendah yang ada di ujung daftar (sebelah kanan) dari daftar nilai yang akan diurutkan menaik.

Rabbit akan lebih cepat untuk diurutkan, sedangkan turtle akan menyebabkan jalannya lama eksekusi dari program pengurutan.

Gimana?! Bisa dimengerti kah? Kalau kamu belum ada bayangan, di sini bisa dilihat contohnya kok. Pertama.. rabbit dulu ya… Rabbit, sesuai definisinya, nilai besar yang ada di ujung sebelah kiri dari daftar yang akan diurutkan menaik. Jadi, contoh valid daftarnya adalah “13 2 4 7 9”. Nilai 13 adalah rabbit. Dan kenapa dia disebut rabbit?! Kita lihat langkah2 pengurutannya:

Kondisi awal: 9 2 4 7 8

First Pass
9 2 4 7 8 --> 2 9 4 7 8 (swapped terjadi)
2 9 4 7 8 --> 2 4 9 7 8 (swapped terjadi)
2 4 9 7 8 --> 2 4 7 9 8 (swapped terjadi)
2 4 7 9 8 --> 2 4 7 8 9 (swapped terjadi)

dikarenakan terjadinya swapped,
maka perbandingan dimulai dari elemen ke-0 sampai ke-(n-1) diulang.

Second Pass
2 4 7 8 9 --> 2 4 7 8 9 (swapped tidak terjadi)
2 4 7 8 9 --> 2 4 7 8 9 (swapped tidak terjadi)
2 4 7 8 9 --> 2 4 7 8 9 (swapped tidak terjadi)
2 4 7 8 9 --> 2 4 7 8 9 (swapped tidak terjadi)

Perulangan berhenti karena swapped tidak terjadi.
Kondisi akhir: daftar terurut menaik.

Lihat kan kenapa dia disebut dengan rabbit?! Cuma butuh 2 pass aja untuk mengurutkan nilainya. Bandingkan dengan turtle berikut. Anggap kita punya daftar nilai 2 4 7 9 1. Nilai 1 adalah turtle karena merupakan nilai kecil yang ada di sebelah kanan daftar yang akan diurutkan menaik:

Kondisi awal: 2 4 7 9 1

First Pass
2 4 7 9 1 --> 2 4 7 9 1 (swapped tidak terjadi)
2 4 7 9 1 --> 2 4 7 9 1 (swapped tidak terjadi)
2 4 7 9 1 --> 2 4 7 9 1 (swapped tidak terjadi)
2 4 7 9 1 --> 2 4 7 1 9 (swapped terjadi)

Second Pass
2 4 7 1 9 --> 2 4 7 1 9 (swapped tidak terjadi)
2 4 7 1 9 --> 2 4 7 1 9 (swapped tidak terjadi)
2 4 7 1 9 --> 2 4 1 7 9 (swapped terjadi)
2 4 1 7 9 --> 2 4 1 7 9 (swapped tidak terjadi)

Third Pass
2 4 1 7 9 --> 2 4 1 7 9 (swapped tidak terjadi)
2 4 1 7 9 --> 2 1 4 7 9 (swapped terjadi)
2 1 4 7 9 --> 2 1 4 7 9 (swapped tidak terjadi)
2 1 4 7 9 --> 2 1 4 7 9 (swapped tidak terjadi)

Fourth Pass
2 1 4 7 9 --> 1 2 4 7 9 (swapped terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)

Fifth Pass
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)
1 2 4 7 9 --> 1 2 4 7 9 (swapped tidak terjadi)

Algoritma berhenti. Kondisi akhir: daftar terurut menaik.

Lihat kan?! Perbandingannya, dengan jumlah data yang sama… rabbit cuma butuh 2 pass, sedangkan turtle butuh 5 pass. Makanya namanya rabbit & turtle. Kelinci yang cepat, dan kura-kura yang lambat. Kata para peneliti, hal ini dikarenakan perbandingan dari bubble sort dilakukan kepada nilai yang tepat berada di sampingnya. Seandainya, perbandingan dilakukan dalam jarak tertentu, kemungkinan hal ini bisa diatasi menjadi lebih baik. Dan hal ini memunculkan algoritma lain, yaitu comb sort.

Well.. untuk hal ini, kita teruskan di tulisan berikutnya aja yah…

Bubble Sort Part 1: Teori & Praktik

Berawal dari tulisan ini yang menahun udah ditulis… saya jadi pengen bikin tulisan ini. Dan… melihat tanggal post-nya.. Can you believe it?! I wrote it 5 years ago! God, udah lumayan lama umur ini blog yah berarti. Dengan pengunjung yang ga nambah berarti tiap tahunnya. Bahkan ada yang sempat komentar, tulisan blog balita bertele-tele banget. Bagusnya langsung ke pokok bahasan ajah. Hahahah…

Baiklah, intinya di sini saya mau tulis tentang bubble sort. Tulisan ini sama kayak tulisan yang berserakan di dunia maya, jadi ga ada spesial2nya. Terus kenapa ditulis?! Kenapa ga cantumin sumber aja?! Yaaa… karena saya mau ngisi blog di tahun baru, itu aja… udah. Ga ada alasan lain. O iya, walaupun di sini kita bahasa bubble sort.. one caveat for you… bubble sort ini pengurutan naive ya! Cetek banget! Ilmu kamu rendah kalau pakai pengurutan ini di kasus yang kamu punya. Untuk alasan apapun, walau ini dibahas sama anak kuliahan, jangan gunakan pengurutan ini untuk tugas2 algoritma dasar (bahkan yang lanjut)! Kecuali kamu disuruh dosen/aspraknya. Algoritma ini simple, tapi worst case-nya punya cost yang bisa dibilang ga minimal.

Kita mulai yah… (iya, baru mulai sekarang inti tulisannya). Dimulai dari konsep pengurutan terlebih dahulu. Teori pengurutan atau sorting, sebenarnya diawali dari pertanyaan gini:

kalau kamu punya sebuah data numerik (kita pakai numerik aja yang gampang dibandingkan)… gimana cara membuktikan bahwa dia sudah terurut atau belum??

Itulah konsep awal dari pengurutan. Simple memang, tapi bayangkan kamu musti ngajarin komputer tentang hal ini. Dan ditambahkan satu hal lagi berupa: “Apa yang dilakukan kalau tidak terurut?!” maka jadilah sebuah algoritma pengurutan.

Bubble sort mengambil konsep ini dengan sederhana. Sebuah daftar dinyatakan terurut atau tidak, kalau sebuah nilai yang berdampingan diletakkan dalam urutan yang seharusnya. Artinya apa?? artinya gini… ketika kamu punya 2 nilai, anggaplah a dan b. Kedua hal dalam posisi yang tetap tersusun dalam bentu “a b“. Maka kedua hal tersebut dinyatakan terurut menaik jika a < b; dan terurut menurun jika a > b. Dan sekarang, bayangkan yang kamu punya adalah sebuah daftar, anggaplah dengan 5 nilai: “a b c d e“. Maka, untuk membuktikan bahwa daftar sudah terurut menaik kalau kamu harus bisa membuktikan 4 kondisi:

  1. a < b
  2. b < c
  3. c < d
  4. d < e

Dengan kata lain, untuk setiap nilai yang bersebelahan, harus memenuhi persyaratan tertentu, entah lebih besar, atau lebih kecil. Hal inilah yang diambil oleh bubble sort:

Pastikan dua nilai yang bersebelahan memenuhi kondisi tertentu. Jika tidak, maka lakukan swapped (menukarkan posisi dari 2 nilai). Lakukan pengecekan berulang sampai swapped tidak terjadi lagi mulai dari awal komponen, sampai akhir komponen.

Contoh:

Diketahui sebuah daftar “3 2 7 6”, kondisi tidak terurut. Daftar harus diurutkan menaik menjadi “2 3 6 7” Maka terdapat beberapa hal yang harus kamu lakukan:

  1. Mulai perulangan dari elemen indeks ke i=0 (nilai 3) sampai i=n-1 (nilai 7). Bandingkan antara bilangan ke-i dan setelahnya.
  2. Jika hasil perbandingan lebih besar, maka tukarkan letaknya (hal ini dinamakan swapped).
  3. Jika swapped terjadi, langkah 1 harus dieksekusi kembali sampai swapped tidak terjadi.

Untuk lebih jelasnya, kita buat gambarannya:

Kondisi awal: "3 2 7 6" 
Kondisi akhir: elemen terurut menaik - "2 3 6 7"

First pass

Bandingkan elemen 0 dengan elemen 1
3 2 7 6 --> 2 3 7 6.
Swapped terjadi di elemen 0 & elemen 1

Bandingkan elemen 1 dengan elemen 2
2 3 7 6 --> 2 3 7 6
Swapped tidak terjadi

Bandingkan elemen 2 dengan elemen 3
2 3 7 6 --> 2 3 6 7
Swapped terjadi

Sampai di sini, kondisi awal dengan kondisi akhir sudah sama. Tapi proses sorting belum berhenti. Ingat bahwa perbandingan harus diulang dari elemen ke-0 sampai ke-n jika ada swapped. Dari proses sebelumnya, swapped terjadi di proses 1 juga proses 3, maka lakukan perbandingan kembali dari awal.

Kondisi sebelumnya: "2 3 6 7" 
Kondisi akhir: elemen terurut menaik - "2 3 6 7"

Second pass

Bandingkan elemen 0 dengan elemen 1
2 3 6 7 --> 2 3 6 7.
Swapped tidak terjadi

Bandingkan elemen 1 dengan elemen 2
2 3 6 7 --> 2 3 6 7
Swapped tidak terjadi

Bandingkan elemen 2 dengan elemen 3
2 3 6 7 --> 2 3 6 7
Swapped tidak terjadi

Dan pada second pass di atas, swapped tidak terjadi sama sekali. Dan algoritma pengurutan pun berhenti. Karena kondisi langkah ke-3 tidak lagi terpenuhi. Dan lihat.. tujuan akhir sudah tercapai.

Proses di atas dibagi ke dalam 2 pass dalam block penjelasan yang berbeda… dan buat lengkapnya, gini proses dari bubble sort itu dituliskan:

Kondisi awal: "3 2 7 6" 
Kondisi akhir: elemen terurut menaik - "2 3 6 7"

First pass
3 2 7 6 --> 2 3 7 6 (swapped terjadi)
2 3 7 6 --> 2 3 7 6 (swapped tidak terjadi)
2 3 7 6 --> 2 3 6 7 (swapped terjadi)

Second pass
2 3 6 7 --> 2 3 6 7 (swapped tidak terjadi)
2 3 6 7 --> 2 3 6 7 (swapped tidak terjadi)
2 3 6 7 --> 2 3 6 7 (swapped tidak terjadi)

Algoritma berhenti karena tidak ada swapped.
Kondisi daftar terurut menaik.

Sekarang, kode-nya seperti apa? Kode-nya sendiri dapat kamu cek di sumber di bawah, kalau yang saya bikin, ada di post ini. Kamu bisa coba…

import java.util.Random;

public class NewClass {

    public int[] randomArray(int jumlah) {
        int[] arr = new int[jumlah];
        Random r = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = r.nextInt(10);
        }
        return arr;
    }

    public int[] urut(int[] arr) {
        int j, temp;
        boolean flag = true;

        while (flag) {
            flag = false;
            for (j = 0; j < arr.length - 1; j++) {
                if (arr[j] > arr[j + 1]){
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    flag = true;
                }
            }
        }
        return arr;
    }
    public void tampilArray(int[] arr){
        for (int i:arr) {
            System.out.print(i+" ");
        }
    }
    public static void main(String[] args) {
        NewClass nc = new NewClass();
        int[] array = nc.randomArray(6);
        System.out.println("Array: ");
        nc.tampilArray(array);
        System.out.println("\n\nArray Terurut: ");
        int[] arrayUrut = nc.urut(array);
        nc.tampilArray(arrayUrut);
    }
}

Kode di atas untuk terurut menurun. Kalau mau mau terurut menaik, bisa ganti tanda “<” jadi “>” di baris ke-21. Untuk mengganti jumlah nilai yang akan diurutkan, bisa ganti parameter input dari method radomArray di baris ke-38. Begitulah… semoga bisa membantu kamu.

Sumber:

Mengubah Format Currency dan Format Rupiah ke dalam Number pada Bahasa Java

Berawal dari lebih dari 1 orang yang nanyain di kotak komentar postingan ini, gw akhirnya bikin dah post ini. Mayan… buat nambah2in isi blog yang agak guna biar ga curcolan mulu isinya…

Singkat cerita, ada yang nanyain gimana cara ngubah format dalam bentuk duit balik lagi ke sifat aslinya (number) biar bisa dioperasiin. Well… buat gw, itu pertanyaan yang bikin gw bingung. Banget! Karena… faktanya, kalau kamu udah punya suatu “a” yang kamu ubah jadi “b”, buat apa kamu ngubah “b” jadi “a”. Toh nilai “a” dari awal udah kamu punya dan nilainya sama sekali ga ketimpa. Beda tipe data gitu… gimana cara isinya bisa ditimpa jadi nilai lain kan yah… Makanya gw bingung.

Tapi apapun itu… ada satu alasan buat para programmer-pemberi-isi-kotak-komentar-di-postingan-asal biar ga ambil lagi nilai awalnya. Dan mereka bingung gimana cara balikinnya. Untuk itu… disinilah gw sebagai pencerah bagi mereka yang kebingungan… Hohoho.

Seperti yang gw tulisin di kotak balasan, ada beberapa langkah yang musti dilakukan:

  1. Parse formatted String ke tipe Number pakai method parse dari objekDecimalFormat
  2. Konversi bentuk Number ke byte/double/float/long/int/short pakai byteValue/doubleValue dst.

Simple kan… buat yang bingung, kodenya gini:

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;

public class KurensiIndonesia {

    public static void main(String[] args) {
        double harga = 250000000;

        DecimalFormat kursIndonesia = (DecimalFormat) DecimalFormat.getCurrencyInstance();
        DecimalFormatSymbols formatRp = new DecimalFormatSymbols();

        formatRp.setCurrencySymbol("Rp. ");
        formatRp.setMonetaryDecimalSeparator(',');
        formatRp.setGroupingSeparator('.');

        kursIndonesia.setDecimalFormatSymbols(formatRp);
        String x = kursIndonesia.format(harga);
        System.out.println("Harga Rupiah: "+x);
//konversi balik String --> number type
        try {
            Number number = kursIndonesia.parse(x);
            double nilai = number.doubleValue();
            System.out.println("Nilai dari rupiah: "+String.format("%.2f", nilai));
        } catch (ParseException ex) {
            System.out.println("Kesalahan Parsing");
        }
    }
}

Hasil:

Capture

Contoh kode yang lebih singkat… cuma buat konversi rupiah ke angka itu gini:

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;

public class KurensiIndonesia {

    public static void main(String[] args) {

        String x = "Rp. 250.000.000,00";
        DecimalFormat kursIndonesia = (DecimalFormat) DecimalFormat.getCurrencyInstance();
        DecimalFormatSymbols formatRp = new DecimalFormatSymbols();

        formatRp.setCurrencySymbol("Rp. ");
        formatRp.setMonetaryDecimalSeparator(',');
        formatRp.setGroupingSeparator('.');

        kursIndonesia.setDecimalFormatSymbols(formatRp);
        try {
            Number number = kursIndonesia.parse(x);
            double nilai = number.doubleValue();
            System.out.println("Nilai dari rupiah: "+String.format("%.2f", nilai));
        } catch (ParseException ex) {
            System.out.println("Kesalahan Parsing");
        }
    }
}

Intinya, pastiin objek DecimalFormat sama DecimalFormatSymbols yang dibentuk itu sama jenisnya. Gampangnya, objek yang digunain buat nge-format sama nge-parse itu sama. Jangan sampe beda. Kalau beda, ada kemungkinan kamu dapat nilai yang salah bahkan kegagalan eksepsi.

Dan karena banyak yang nanya juga terkait swing dan lainnya… hal di atas gw juga udah coba ke swing (pakai jtextfield biasa) sama akses database (nyimpen ke Access–biar gw ga usah nginstall dbms lagi)…. dan berhasil.

Moga ngebantu urusan kamu masing-masing…

Baca juga: Mengubah nilai double –> rupiah.

Memberi Input Argument Pada Netbeans

Di tulisan perdana pasca recovery, ternyata gw ga nyeritain tentang kondisi gw. Hohoho… ntar ajah… abis gw checkup beberapa hari lagi.

Jadi sekarang, ceritanya gw mau kasih tau gimana cara nge-set argument kalo pake IDE Netbeans. Hal remeh c sebenernya. Tapi berhubung ga ada yang mau ditulisin lagi, dan masih banyak temen junior gw yang bingung caranya…. Jadi aja gw tulis di mari.

Buat kamu yang belajar Java pertama kali, kemungkinan kamu dikasih tau sama pelatihnya, kalo masukannya bisa dimasukin via argumen java. Argumen ini ditulisin pas kita mau ngejalanin programnya. Contohnya, anggap gw punya kode kayak gini:

public class Main {

    public static void main(String[] args) {
        int a = Integer.parseInt(args[0]);
        int b = Integer.parseInt(args[1]);
        int c = a + b;
        System.out.println("Jumlah " + a + " + " + b + " = " + c);
        System.out.println(args[0]);
    }
}

yang bakal gw eksekusi pake kode ini di command line interface (CLI):

java Main 10 20

trus ngehasilin hasil kayak gini:

Jumlah 10 + 20 = 30
10

Buat pengguna Netbeans, biasanya bakal bingung… gimana cara ngetik tambahan input parameter berupa angka 10 sama 20 itu. Sebenernya, dari sejak jaman Netbeans tercipta, fitur ini tuh udah ada. Cuma, pas awal2… parameternya cuma bisa buat 1 main class yang dijalanin buat 1 project. Kalo kamu punya 2 main class di 1 project (dalam rangka eksperimen atau apapun), main class yang kedua ga bakal bisa dijalanin. Tapi herannya, para senior (maksudnya asprak pas nguli) dulu ga ngajarin kita hal ini. Dosen juga enggak. Mungkin karena gampang kali yah… Apapun alasannya, di sini, gw bakal kasih tau caranya biar bisa tambahin argument ini di Netbeans. Jadi berterima kasihlah kamu semua ke gw yang lebih baik dari kaka asprak juga dosennya kamu… XD

Cara pertama yang gw kasih tau… yaitu cara awal pas running Netbeans dari jaman dulu.

Awalnya,  konfigurasi dilakukan dari Run -> Set Project Configuration -> Customize…

konfigurasi-run

Setelah muncul pop-up window, masukkan nilai yang ingin diberikan untuk argumen pada text field Arguments.

konfigurasi-argumen

Kalau udah di-OK, pas tekan F6 untuk Run File, bakal muncul hal kayak gini:

hasil-run

Cara kedua… kalo ga salah baru muncul pas Netbeans versi 7. Gw ga tau tepatnya kapan… tapi mulai dari versi 7.4 sampe 8.2 (yang gw pake sekarang), udah muncul nih fitur. Caranya, di layar output, pilih segitiga kuning dari bagian output… terus, bakal muncul kan satu window pop-up… kasih tambahan tulisan gini:

konfigurasi-argumen-output

Terus dampaknya mirip sama output di atas, bedanya masukan argumen jadi 20 ama 30… Bukan kayak awal (10 dan 20).

Hal yang perlu diperhatikan dari cara kedua, kamu semua bener2 harus nulisin “application.args”. Jangan sekali2 kamu nuker “args” jadi “arg” atau yang lain gara2 kamu ga nulis “public static void main(String[] args)” tapi malah nulis “public static void main(String[] arg)”. Best practice yang lain, pengaturan ini munculnya dari window output. Jadi, gampangnya… pastiin kamu udah nge-running minimal 1x error… baru kamu tekan kuning2nya. Pas running pertama, pasti bakal error… kecuali kamu udah ngelakuin cara pertama untuk class yang mau kamu running.

Sooo… gitu ajah. Kalau ada masukan plus koreksi, boleh banget tulisin di kotak komentar…

Menggunakan notify Pada NotifyDescriptor Netbeans Platform

Gw agak2 heran c yah… kenapa beberapa waktu terakhir banyak banget yang nanyain tentang Netbeans Platform ke gw. Padahal kan gw jugak dah lumayan lama gak nyentuh2 NetPla. Tapi ya sudahlah yah… Reader tetep ajah reader yang bisa jadi inspirasi blogger buat nulis sesuatu.

Okeh! Jadi, berangkat dari tujuan itu, gw nulisin nih tulisan.

Topik yang ditanyain yaitu terkait NotifyDescriptor plus temennya DialogDisplayer. Terkait 2 hal itu, gw asumsiin kamu semua dah pada tau dua hal itu apa yah… Intinya, NotifyDescriptor itu komponen di NetPla yang punya fungsi mirip sama JOptionPane. Bedanya, kalo di JOptionPane, kamu cuma nentuin konten (gambar, kata2, judul, tombol de el el). Sedangkan di NotifyDescriptor, kamu bisa desain sendiri apa yang kamu tampilin. Mulai dari jumlah masukan yang kamu mau, tombol apa yang ditampilin, bahkan warna panel yang kamu sukak buat ditampilin ke pengguna aplikasi yang kamu bikin. Itu gunanya si NotifyDescriptor. Terus, si DialogDisplayer punya fungsi buat munculin si NotifyDescriptor biar bisa muncul di hadapan pengguna. Okeh.. itu intinya.

Pertanyaan aslinya, yaitu tentang menampilkan objek NotifyDescriptor dari DialogDisplayer. Faktanya, di sini kamu bisa nampilin dengan menggunakan 2 method, yaitu “notify” sama “notifyLater”. Dan yaaa… itulah pertanyaannya. Apa bedanya cara nampilin pake “notify” sama “notifyLater”?

Jawaban gw c singkat ajah ya… Bedanya… kamu baca deh netbeans doc. Ntar juga ketemu. Atau kalo males, nih gw kutip dokumentasinya.

public abstract Object notify(NotifyDescriptor descriptor)

Notify the user of something in a message box, possibly with feedback.

To support both GUI and non-GUI use, this method may be called from any thread (providing you are not holding any locks), and will block the caller’s thread. In GUI mode, it will be run in the AWT event thread automatically. If you wish to hold locks, or do not need the result object immediately or at all, please make this call asynchronously (e.g. from the request processor).

Parameters:
descriptor – description of the notification

Returns:
the option that caused the message box to be closed

Yang atas buat notify, yang bawah buat notifyLater

public void notifyLater(NotifyDescriptor descriptor)

Notify the user of something in a message box, possibly with feedback, this method method may be called from any thread. The thread will return immediately and the dialog will be shown later, usually when AWT thread is empty and can handle the request.

Implementation note: Since version 7.3, implementation improved to work also before main window is opened. For example: When method is called from ModuleInstall.restored, then modal dialog is opened and blocks main window until dialog is closed. Typical use case is login dialog.

Parameters:
descriptor – description of the notification

Since:
7.0

Jadi intinya, yang atu method berupa prosedur (notifyLater), atunya berupa function (notify). Jadi yang satunya mengharapkan adanya nilai balikan pas pemanggilannya, satunya lagi enggak. Sesuai sama sifat fungsi atau prosedur. Terus, kapan kita musti ngegunain salah satunya dibanding yang lain?! Jawabannya juga bisa kamu liat di atas. Kalo seandainya kamu musti nampilin sesuatu sebelum main window muncul, bisa pake notifyLater.

Gak ada salahnya juga kamu make notify. Tapi ati2 ajah ama kode kamu. Karena ga sekali dua kali gw nemu kejadian kalo aplikasinya masih jalan secara background walo main window-nya udah ditutup karena programmernya (iya, gw c maksudnya) make notify, dan bukannya notifyLater.

Kalo seandainya ada satu kondisi yang ngeharusin kamu pake notify dan bukannya notifyLater, padahal kamu musti nampilin message box-nya sebelum main window ke-load, kamu bisa kasih aksi ke si objek NotifyDescriptor-nya gini:

        DialogDisplayer.getDefault().notify(nd);

        nd.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getNewValue().equals(NotifyDescriptor.CLOSED_OPTION)) {
                    LifecycleManager.getDefault().exit();
                } else if (evt.getNewValue().equals(NotifyDescriptor.OK_OPTION)) {
                    //logika
                } else {
                    LifecycleManager.getDefault().exit();
                }
            }
        });

Cukup jelas kan yah? Hal di atas perlu kamu lakuin. Kenapa?! Karena kalo enggak, pas nutup message box-nya, program kamu ada kemungkinan masih jalan sebagai proses background. Gak bagus buat pengguna kamu. Tiba2 memorinya penuh gara2 aplikasi yang kamu bikin. Command exit() gak bakal ngaruh dalam pengkondisian penyamaan objek yang merupakan balikan dari pemanggilan notify(). Jadi ati2 yah…

Dan begitulah caranya… maaf yak kalo ternyata ga terlalu jelas. Cuma segitu yang bisa gw bagi. Maaf jugak, buat kali ini gw gak nyantumin sumber plus info kevalidan buat hal di atas. Yah… gitu deh…

Membuka Actived TopComponent pada Action Netbeans Platform

Jadi… yang namanya action di Netbeans Platform, emang dimaksudkan buat hal2 yang sifatnya universal, kayak copy-paste, nampilin Wizard, dan hal2 sejenis lainnya. Cuma ajah, kadang kita nemu kasus khusus yang musti ngebikin kita ngebentuk satu tombol buat beberapa aksi berbeda, tergantung window yang aktif.

Kalo udah kayak gini, banyak hal bisa kamu lakuin, salah satu caranya gini:

  1. Ambil window yang aktif dari registry terlebih dahulu.
  2. Cek apakah instance dari TopComponent yang diambil sesuai dengan yang diinginkan.
  3. Lakukan aksi yang diperlukan.

Buat kamu yang pengin detail, sayangnya gw gak bakal publish di mari. Tapi bakal gw kasih sedikit source buat ngebantu. Langkah pertama: ambil TopComponent window yang aktif:

TopComponent tc = WindowManager.getDefault().getRegistry().getActivated();

Langkah kedua: cek instance dari TopComponent

if(tc instanceof UtamaTopComponent){
}

Buat langkah ketiga, lakukan seperlunya. Kamu bisa casting plus manggil method terkait dari TopComponent yang udah diambil tadi. Contohnya gini:

        if(tc instanceof UtamaTopComponent){
            UtamaTopComponent uc = (UtamaTopComponent) WindowManager.getDefault().findTopComponent("UtamaTopComponent");
            uc.cekHasilMod();
        }    

Begitulaahhh… sorry kalo gak terlalu ngebantu.

Membatasi Input Angka pada JTextField

Kita bahas trik lawas yak… trik apa?! Ya… sesuai judul postingan aja. Biar agak beda, di sini, gw pake 2 cara dan ngebahas beberapa hal terkait 2 cara tersebut. Langsung ajah, bentuk GUI kayak gini:

1. Contoh AplikasiKlik kanan di bagian teks buat Key Event, Pilih “Events” → “Key” → “Key Typed”, ntar muncul satu kode kayak gini:

2. Kode Key EventDalam logikanya, tulisin gini:

        char c = evt.getKeyChar();
        if (!((Character.isDigit(c) || (c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE)))) {
            evt.consume();
        }

Seperti yang kamu semua liat, di sana dipakein 3 kondisi:

  1. Cek kalo karakter yang di-type ama user gak termasuk ke dalam bentuk digit. Digit yang dimaksud masuk dalam ISO-LATIN, Arabic-Indic, Extended Arabic-Indic, Devanagari, dan Fullwidth.
  2. Cek karakter yang ditekan itu merupakan karakter backspace.
  3. Cek karakter yang ditekan itu merupakan karakter delete.

Kalo aja salah satu kondisi tersebut terpenuhi, yaaa… bakal dimasukin ke teks field. Kalo gak, yaaa… gak bakal kebaca sebagai karakter yang dimasukin. Kelemahannya apa?! Kelemahannya, karakter lain tetep bisa dimasukin. Caranya?! Simple… Copy-Paste… Nih yah, gambarnya gw tunjukin. Text field-nya dah gw pakein key event, tapi tetep bisa masuk karakter lain.

3. Kelemahan Event Type

Cara ngatasinya?! Yaaaa.. kamu cari tau aja sendiri. Tapi kalo emang kamu segitu mohon2nya ama gw, baiklah… gw kasi tau caranya. Caranya, cukup setTransferHandle jadi null untuk komponen terkait. Kode ini, bisa diletakin di bagian konstruktor.

Best practice-nya gini, anggap text field yang mau kamu pake namanya jTextField1, jadi di bagian konstruktor, tambahin kode gini:

jTextField1.setTransferHandler(null);

Tapi kode di atas jugak gak memungkinkan kamu buat ngelakuin copy yah. Ati2 ajah. Terus gimana alternatifnya?! Solusi lain yang bisa kamu lakukan, dengan tidak melakukan apa pun ketika tombol Ctrl+V ditekan. Ini punya kelemahan juga c… Bayangin kalo di suatu mesin, paste gak di-peta-in pake tombol Ctrl+V, ini bakal jadi masalah. Tapi, beruntungnya… copy/paste sifatnya universal untuk tiap mesin. Jadi… moga aman lhah… 😀

Oke… best practice-nya, bikin suatu key stroke, dan petain ke aksi yang gak ngelakuin apa pun. Kalo gw, nambahin kodenya deket2 konstruktor. Gini nih kodenya. Yang warnanya biru, itu yang gw tambahin. Lebihnya, itu standar bentuk JFrame awal.

    public NewJFrame() {
        initComponents();
        KeyStroke ks = KeyStroke.getKeyStroke("control V");
        jTextField1.getInputMap().put(ks, "dummy");

    }
    Action dummy = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            //do nothing
        }
    };

4. Key Stroke
Kalo udah nambahin kayak yang di atas, copy bisa dilakuin, tapi paste udah gak bisa. Jangan lupa buat uncomment kode setTransferHandle, plus import package terkait yak… Paling gak, kamu musti import 5 class ini:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.KeyStroke;

Okeh… itu cara pertama yah… Cara yang kedua, pake PlainDocument.

Deklarasiin sebuah objek dari PlainDocument, kayak gini:

    PlainDocument pd = new PlainDocument() {
        @Override
        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
            if (str.matches("[0-9]*")) {
                super.insertString(offs, str, a);
            } else {
                // do nothing
            }
        }
    };

Terus, kalo udah deklarasiin satu dokumen, berikutnya hubungkan objek PlainDocument ke text field yang diinginkan (di tulisan ini, maksudnya jTextField2). Jadi, gw tambahin kode kayak gini, di baris paling akhir sebelum kurung kerawal tutup dari konstruktor.

jTextField2.setDocument(pd);

Kekurangannya?! Hummm… hampir gak ada c, copy/paste udah terlarang di sini. Karena bukan cuma key event yang ditangani, tapi konten dokumennya jugak. Yang jadi permasalahan, even gak bisa paste, tapi kalo kamu blok semua karakter (pake Ctrl+A), terus kamu tekan Ctrl+V, dokumen semuanya bakal ilang. Cara nanganin?! Hmmm… pake aja cara penanganan sebelumnya. Selesai deh.

Oke, segitu ajah.. Moga ngebantu yak.

Sumber:
https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
http://www.coderanch.com/t/341695/GUI/java/enable-CTRL-perform-action-coping
http://stackoverflow.com/questions/316673/disabling-paste-in-a-jtextfield
http://www.atwiwit.net/2013/10/java-programming-cara-membuat-input.html
http://khannedy.com/2010/06/28/agar-jtextfield-tidak-menerima-input-selain-angka/

Valid: Yap
Kadaluarsa: (?)