Bab.3 Pemrograman
Event-Driven
Tujuan Instruksional
|
|
·
Menjelaskan event, sumber event, dan
kelas-kelas event.
·
Mendefinisikan kelas listener, objek listener
register dengan objek sumber.
·
Mendefinisikan kelas listener menggunakan
kelas inner (kelas sebelah dalam).
·
Mendefinisikan kelas listener menggunakan
kelass inner tak-bernama.
·
Mengeksplorasi berbagai gaya pengkodean untuk
menciptakan dan meregistrasi listener.
|
·
Mendapatkan masukan dari bidang teks setelah
penekanan tombol.
·
Menulis program untuk menangani WindowEvent.
·
Menyederhanakan pengkodean untuk kelas
listener menggunakan adapter antarmuka listener.
·
Menulis program untuk menangani MouseEvent.
·
Menulis program untuk menangani KeyEvent.
·
Menggunakan kelas javax.swing.Timer untuk mengendalikan animasi.
|
3.1
Introduksi
Dimisalkan Anda ingin menulis suatu program
GUI yang mengijinkan pengguna untuk memasukkan jumlah hutang, suku bunga
tahunan, dan jumlah tahun pinjaman dan menekan tombol Hitung Hutang untuk
mendapatkan pembayaran bulanan dan total pembayaran, seperti ditunjukkan pada Gambar
3.1a. Bagaimanakah Anda menyelesaikan masalah tersebut? Anda harus menggunakan
pemrograman event-driven untuk menulis kode yang merespon event
penekanan-tombol.
Gambar 3.1 Program menghitung pembayaran hutang
Dimisalkan pula Anda ingin menulis suatu
program untuk menganimasi suatu bendera yang sedang berkibar. Bagaimana Anda
mengatasi hal ini? Ada beberapa cara mengatasi hal ini. Salah satu cara yang
efektif adalah menggunakan timer atau pewaktu dalam pemrograman event-driven,
yang merupakan subjek pembahasan dalam bab ini.
Di dalam pemrograman event-driven, kode
dieksekusi ketika suatu event terjadi (misalnya oleh pengklikan tombol, oleh
pergerakan mouse, atau oleh timer).
3.2
Event dan Sumber Event
Ketika
Anda menjalankan suatu program GUI JAVA, program berinteraksi dengan pengguna,
dan event menyetir arah eksekusi. Event didefinisikan sebagai suatu sinyal
kepada program bahwa sesuatu telah terjadi. Event dipicu oleh aksi pengguna
eksternal, seperti pergerakan mouse, pengklikan tombol, dan penekanan
papan-kunci, atau oleh aktivitas program internal, seperti timer. Program dapat
memilih untuk merespon atau mengabaikan event yang terjadi.
Komponen
yang menciptakan suatu event dan memicunya disebut dengan objek sumber atau
komponen sumber. Sebagai contoh, suatu tombol adalah objek sumber untuk event
pengklikan-tombol. Event merupakan instans dari suatu kelas event. Kelas akar
dari kelas-kelas event adalah java.util.EventObject.
Relasi hirarhki atas beberapa kelas event ditampilkan pada Gambar 3.2.
Gambar
3.2 Event adalah suatu objek dari
kelas EventObject
Objek
event memuat properti-properti yang melekat pada event terkait. Anda dapat mengidentifikasi
objek sumber dari suatu event menggunakan metode instans getSource() di dalam kelas EventObject.
Sub-subkelas dari EventObject
digunakan untuk menangani tipe-tipe event tertentu, seperti event aksi, event
jendela, event komponen, event mouse, dan event kunci. Tabel 3.1 menyimpulkan
aksi pengguna eksternal, objek sumber, dan tipe event yang dipicu.
3.3
Listener, Registrasi, dan Penanganan Event
JAVA
menggunakan model berbasis delegasi dalam menangani event: Suatu objek sumber
memicu event, dan suatu objek menangani event tersebut. Objek yang terakhir ini
disebut dengan listener. Agar suatu objek dapat menjadi listener untuk event
yang dipicu oleh objek sumber, dua hal diperlukan, seperti ditampilkan pada
Gambar 2.3.
Tabel
3.1 Aksi Pengguna, Objek Sumber, dan
Tipe Event
Aksi Pengguna
|
Objek Sumber
|
Tipe Event
|
Pengklikan suatu tombol
Hasil pengisian pada bidang teks
Pemilihan suatu item baru
Pemilihan item
Pengklikan suatu kotak periksa
Pengklikan suatu kotak radio
Memilih suatu item menu
Menggerakkan batang penggeser (scroll bar)
Menggerakkan batang penggeser (scroll bar)
Jendela dibuka, ditutup, dll
Mouse ditekan, dilepas, dll
Menggeser atau menggeret (drag) mouse
Melepas atau menekan kunci pada papan-ketik.
Komponen ditambahkan atau dihapus dari kontainer
Komponen digeser, diubah ukurannya, disembunyikan,
atau ditampilkan
Komponen dikaburkan atau difokuskan
|
JButton
JTextField
JComboBox
JList
JCheckBox
JRadioButton
JMenuItem
JScrollBar
JSlider
Window
Component
Component
Component
Container
Component
Component
|
ActionEvent
ActionEvent
ItemEvent, ActionEvent
ListSelectionEvent
ItemEvent, ActionEvent
ItemEvent, ActionEvent
ActionEvent
AdjustmentEvent
ChangeEvent
WindowEvent
MouseEvent
MouseEvent
KeyEvent
ContainerEvent
ComponentEvent
FocusEvent
|
1.
Objek listener harus merupakan instans dari antarmuka event-listener
untuk memastikan bahwa listener memiliki metode yang tepat dalam memproses
event. JAVA menyediakan suatu antarmuka listener untuk setiap jenis event.
Antarmuka listener biasanya dinamai XListener
untuk XEvent, dengan eksepsi MouseMotionListener. Sebagai contoh,
antarmuka listener untuk ActionEvent
adalah ActionListener; Setiap
listener untuk ActionEvent harus
mengimplementasikan antarmuka ActionListener.
Tabel 3.2 mencantumkan jenis-jenis event, antarmuka listener, metode-metode
yang didefinisikan di dalam antarmuka listener.
2. Objek listener harus diregistrasi oleh objek sumber.
Metode-metode registrasi bergantung pada tipe event. Untuk ActionEvent, metodenya adalah addActionListener.
Pada umumnya, metode dinamakan addXListener
untuk XEvent. Suatu objek sumber
dapat memicu beberapa tipe event. Objek sumber menetapkan daftar listener
terregistrasi dan memberitahukan kepada listener dengan cara memanggil handler
dari objek listener untuk merespon event, seperti tertampil pada Gambar 3.4.
(Gambar 3.4 menampilkan implementasi internal dari suatu kelas sumber. Untuk
menggunakannya, Anda tidak perlu mengetahui bagaimana suatu kelas sumber,
seperti JButton, diimplementasikan.
Akan tetapi, dengan mengetahui implementasi kelas, Anda akan lebih mengerti
pemrograman event-drivent JAVA).
Gambar
3.3 Listener merupakan instans dari
antarmuka listener dan harus diregistrasi dengan suatu komponen sumber
Diinginkan
untuk merevisi kode1.8, PenangananEvent.java. Karena objek JButton memicu ActionEvent,
suatu objek listener untuk ActionEvent
harus berupa instans dari ActionListener,
sehingga kelas listener mengimplementasikan ActionListener pada baris 34. Objek sumber memanggil addActionListener(listener) untuk
meregistrasi suatu listener, sebagai berikut:
JButton jbtOK = new
JButton("OK");
// Baris 7 dalam kode14.8
ActionListener listener1
= new OKListenerClass();
// Baris 18 dalam kode14.8
jbtOK.addActionListener(listener1);
// Baris 20 dalam kode14.8
Ketika
Anda mengklik suatu tombol, objek JButton
memicu suatu ActionEvent dan
melewatkannya untuk memanggil metode actionPerformed
dari listener untuk menangani event.
Tabel
3.2 Event, Event Listener, dan Metode
Listener
Kelas Event
(Handler)
|
Antarmuka
Listener
|
Metode
Listener
|
ActionEvent
ItemEvent
MouseEvent
KeyEvent
WindowEvent
ContainerEvent
ComponentEvent
FocusEvent
AdjustmentEvent
ChangeEvent
ListSelectionEvent
|
ActionListener
ItemListener
MouseListener
MouseMotionListener
KeyListener
WindowListener
ContainerListener
ComponentListener
FocusListener
AdjustmentListener
ChangeListener
ListSelectionListener
|
actionPerformed(ActionEvent)
itemStateChanged(ItemEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mouseClicked(MouseEvent)
mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
windowClosing(WindowEvent)
windowOpened(WindowEvent)
windowIconified(WindowEvent)
windowDeiconified(WindowEvent)
windowClosed(WindowEvent)
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
componentAdded(ContainerEvent)
componentRemoved(ContainerEvent)
componentMoved(ComponentEvent)
componentHidden(ComponentEvent)
componentResized(ComponentEvent)
componentShown(ComponentEvent)
focusGained(FocusEvent)
focusLost(FocusEvent)
adjustmentValueChanged(AdjustmentEvent)
stateChanged(ChangeEvent)
valueChanged(ListSelectionEvent)
|
Objek
event memuat informasi yang terkait dengan event tersebut, yang dapat diperoleh
menggunakan metode-metode, seperti tertampil pada Gambar 3.5. Misalnya, Anda
dapat menggunakan metode e.getSource()
untuk memperoleh objek sumber agar dapat menentukan apakah objek sumber
tersebut adalah tombol, kotak periksa, atau kotak radio. Untuk suatu event
aksi, Anda dapat menggunakan e.getWhen()
untuk memperoleh waktu ketika event terjadi.
Gambar
3.4 Objek sumber memberitahukan
listener event terkait dengan memanggil handler dari objek listener tersebut.
Gambar
3.5 Anda dapat menggunakan informasi
berguna dari suatu objek event
Sekarang
Anda dapat menulis suatu program yang menggunakan dua tombol untuk
mengendalikan ukuran suatu lingkaran, seperti ditunjukkan pada Gambar 3.6.
Program ini akan dikembangkan secara bertahap. Pertama, akan ditulis program
pada kode3.1 yang menampilkan antarmuka pengguna dengan suatu lingkaran di
tengah (baris 14) dan dua tombol di bawah (baris 15).
Kode3.1 KendaliLingkaran1.java
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
|
import javax.swing.*;
import java.awt.*;
public class KendaliLingkaran1 extends JFrame {
private JButton jbtPerbesar = new
JButton("Perbesar");
private JButton jbtPerkecil = new
JButton("Perkecil");
private
PanelLingkaran kanvas = new PanelLingkaran();
public KendaliLingkaran1() {
JPanel panel = new JPanel(); // Menggunakan panel untuk mengelompokkan tombol
panel.add(jbtPerbesar);
panel.add(jbtPerkecil);
this.add(kanvas, BorderLayout.CENTER); //
Menambah kanvas ke tengah
this.add(panel, BorderLayout.SOUTH); //
Menambahkan tombol ke frame
}
/** Metode utama */
public static void main(String[]
args) {
JFrame frame = new
KendaliLingkaran1();
frame.setTitle("KendaliLingkaran1");
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
class PanelLingkaran extends JPanel {
private int radius = 5; // Radius
lingkaran default
/** Menggambar lingkaran */
protected void
paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius,
2 * radius, 2 * radius);
}
}
|
Bagaimana
Anda memperbesar atau memperkecil lingkaran? Ketika tombol Perbesar diklik,
Anda menginginkan lingkaran tersebut digambarkan dengan radius yang lebih
besar. Bagaimana Anda melakukannya? Anda dapat mengembangkan program pada
kode3.1 menjadi kode3.2 dengan fitur-fitur tambahan sebagai berikut:
1. Mendefinisikan
suatu listener bernama PerbesarListener
yang mengimplementasikan ActionListener
(baris 31-35).
2. Menciptakan
suatu listener dan meregistrasikannya dengan jbtPerbesar (baris 18).
3. Menambahkan
suatu metode bernama perbesar() di
dalam PanelLingkaran untuk menambah
radius, dan kemudian menggambar-ulang panel (baris 41-44).
4. Mengimplementasikan
metode actionPerformed di dalam PerbesarListener untuk memanggil kanvas.perbesar() (baris 33).
5. Membuat
variabel referensi kanvas agar dapat
diakses dari metode actionPerformed,
dan mendefinisikan PerbesarListener
sebagai kelas inner (sebelah dalam) di dalam kelas KendaliLingkaran2 (baris 31-35). Kelas inner adalah kelas yang
didefinisikan di dalam kelas lain.
6. Untuk
menghindari error kompolasi, kelas PanelLingkaran
(baris 37-52) sekarang juga didefinisikan sebagai suatu kelas inner di dalam KendaliLingkaran2, karena kelas PanelLingkaran yang lama telah
didefinisikan pada kode3.1.
Gambar
3.6 Pengguna mengklik tombol Perbesar
dan Perkecil untuk memperbesar dan memperkecil radius suatu lingkaran
Kode3.2 KendaliLingkaran2.java
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
|
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class KendaliLingkaran2 extends JFrame {
private JButton jbtPerbesar = new
JButton("Perbesar");
private JButton jbtPerkecil = new
JButton("Perkecil");
private
PanelLingkaran kanvas = new PanelLingkaran();
public KendaliLingkaran2() {
JPanel panel = new JPanel(); // Menggunakan panel untuk mengelompokkan tombol
panel.add(jbtPerbesar);
panel.add(jbtPerkecil);
this.add(kanvas, BorderLayout.CENTER); //
Menambah kanvas ke tengah
this.add(panel, BorderLayout.SOUTH); //
Menambah tombol ke frame
jbtPerbesar.addActionListener(new PerbesarListener());
}
/** Metode utama */
public static void main(String[]
args) {
JFrame frame = new
KendaliLingkaran2();
frame.setTitle("KendaliLingkaran2");
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
class
PerbesarListener implements ActionListener {// Kelas inner
public void actionPerformed(ActionEvent e) {
kanvas.perbesar();
}
}
class PanelLingkaran extends
JPanel {// Kelas inner
private int radius = 5; // Radius
lingkaran default
/** Perbesar lingkaran */
public void perbesar() {
radius++;
repaint();
}
/** Menggambar-ulang lingkaran */
protected void
paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(getWidth() / 2 - radius,
getHeight() / 2 - radius,
2 * radius, 2 * radius);
}
}
}
|
Dengan
cara yang sama, Anda dapat menambahkan kode untuk tombol Perkecil untuk
menampilkan lingkaran lebih kecil ketika tombol Perkecil diklik.
3.4
Kelas Inner
Suatu
kelas inner, kelas nested atau kelas
sebelah dalam, adalah kelas yang didefinisikan di dalam skop kelas lain. Kode
pada Gambar 3.7a mendefinisikan dua kelas terpisah, Test dan A. Kode pada
Gambar 3.7b mendefinisikan A sebagai kelas inner di dalam kelas Test.
Gambar
3.7 Kelas-kelas inner
mengkombinasikan kelas-kelas dependen ke dalam kelas primer
Kelas InnerClass yang didefinisikan di dalam
kelas OuterClass pada Gambar 3.7c
merupakan suatu contoh lain dari kelas inner. Kelas inner dapat digunakan sama
seperti kelas biasa. Normalnya, Anda mendefinisikan suatu kelas sebagai kelas
inner bila kelas tersebut hanya digunakan oleh kelas outernya. Suatu kelas inner
memiliki fitur-fitur sebagai berikut:
·
Kelas inner dikompilasi ke dalam suatu kelas yang
dinamakan NamaKelasOuter$NamaKelasInner.class.
Sebagai contoh, kelas inner A di dalam Test dikompilasi ke dalam Test$A.class, seperti tertampil pada
Gambar 3.7a.
·
Kelas inner dapat mereferensi metode dan data yang
didefinisikan di dalam kelas outernya, sehingga Anda tidak perlu melewatkan
referensi dari suatu objek kelas outer kepada konstruktor kelas inner. Karena
hal ini, kelas inner dapat membuat program singkat dan padat.
·
Kelas inner dapat didefinisikan dengan suatu
pemodifikasi visibilitas yang memiliki aturan yang sama dengan anggota kelas.
·
Kelas inner dapat didefinisikan static. Suatu kelas inner static
dapat diakses menggunakan nama kelas outernya. Kelas inner static tidak dapat mengakses anggota-anggota kelas outer yang
nonstatik.
·
Objek suatu kelas inner seringkali diciptakan di luar
kelas outer. Tetapi Anda juga bisa menciptakan objek kelas inner di luar kelas
lain. Jika kelas inner nonstaik, Anda terlebih dahulu menciptakan instans dari
kelas outer, kemudian menggunakan sintaks berikut untuk menciptakan suatu objek
untuk kelas inner:
KelasOuter.KelasInner
objekInner = objekOuter.new KelasInner();
·
Jika kelas inner static,
maka sintaks berikuti ini digunakan untuk menciptakan suatu objek untuk kelas
inner:
KelasOuter.KelasInner objekInner = new
KelasOuter.KelasInner();
Kegunaan
sederhana dari kelas inner adalah menggabungkan kelas-kelas dependen ke dalam
kelas primer. Hal ini akan mengurangi jumlah kode sumber. Hal ini juga membuat
file-file kelas mudah untuk diorganisasi, karena semuanya dinamai dengan kelas
primer sebagai prefiks. Sebagai contoh, daripada menciptakan dua file sumber, Test.java dan A.java, pada Gambar 3.7a, Anda dapat menggabungkan kelas A ke dalam kelas Test dan menciptakan hanya satu file sumber Test.java, seperti pada Gambar 3.7b. File kelas yang dihasilkan
adalah Test.class dan Test$A.class.
Kegunaan
lain dari kelas inner adalah untuk menghindari konflik penamaan kelas.
3.5
Listener Kelas Tak-Bernama
Suatu
kelas listener didesain secara spesifik untuk menciptakan objek listener untuk
komponen GUI tertentu (misalnya, suatu tombol). Kelas listener tidak dapat
dipakai bersama oleh aplikasi-aplikasi lain dan oleh karena itu cocok untuk didefinisikan
di dalam kelas frame sebagai kelas inner.
Listener
kelas inner dapat disingkat menggunakan kelas inner tak-bernama. Terindikasi
dari namanya, kelas inner tak-bernama adalah suatu kelas inner yang tidak
memiliki nama. Kelas tersebut menggabungkan kelas inner dan menciptakan suatu
instans dari kelas tersebut dalam satu langkah. Kelas inner pada kode3.2 dapat
diganti dengan kelas inner tak-bernama, seperti ditunjukkan berikut ini.
Sintaks
untuk kelas inner tak-bernama adalah sebagai berikut:
new NamaKelasSuper/NamaAntarmuka()
{
// Metode pengimplementasi atau pengoverride di dalam kelas super atau
antarmuka
// Metode-metode lain jika diperlukan
}
Karena
kelas inner tak-bernama merupakan kasus spesial dari suatu kelas inner, maka
kelas ini diperlakukan sama dengan kelas inner lain dengan beberapa fitur
tambahan sebagai berikut:
·
Kelas inner tak-bernama harus selalu mewarisi suatu
superkelas atau mengimplementasikan suatu antarmuka, tetapi kelas ini tidak
boleh memiliki klausa extends atau implements secara eksplisit.
·
Kelas inner tak-bernama harus mengimplementasikan
semua metode abstrak yang ada di dalam kelas super atau di dalam antarmuka.
·
Kelas inner tak-bernama selalu menggunakan konstruktor
tanpa-argumen dari superkelas untuk menciptakan suatu instans. Jika kelas inner
tak-bernama mengimplementasikan antarmuka, maka konstruktornya adalah Object().
·
Kelas inner tak-bernama dikompilasi ke dalam suatu
kelas bernama NamaKelasOuter$n.class.
Sebagai contoh, dimisalkan kelas outer Test
memiliki dua kelas inner tak-bernama, maka keduanya dikompilasi menjadi Test$1.class dan Test$2.class.
Kode3.3
menyajikan suatu contoh dalam menangani event-event dari empat tombol, seperti
ditampilkan pada Gambar 3.8.
Kode3.3 DemoListenerTakBernama.java
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
|
import javax.swing.*;
import java.awt.event.*;
public class DemoListenerTakBernama extends JFrame {
public DemoListenerTakBernama() {
// Menambahkan empat tombol
JButton jbtBaru = new
JButton("Baru");
JButton jbtBuka = new
JButton("Buka");
JButton jbtSimpan = new
JButton("Simpan");
JButton jbtTampil = new
JButton("Tampil");
// Menciptakan panel untuk memuat empat
tombol
JPanel panel = new JPanel();
panel.add(jbtBaru);
panel.add(jbtBuka);
panel.add(jbtSimpan);
panel.add(jbtTampil);
add(panel);
// Menciptakan dan meregistrasi listener
kelas inner tak-bernama
jbtBaru.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Proses baru");
}
}
);
jbtBuka.addActionListener(
new ActionListener() {
public void
actionPerformed(ActionEvent e) {
System.out.println("Proses
membuka");
}
}
);
jbtSimpan.addActionListener(
new ActionListener() {
public void
actionPerformed(ActionEvent e) {
System.out.println("Proses
menyimpan");
}
}
);
jbtTampil.addActionListener(
new ActionListener() {
public void
actionPerformed(ActionEvent e) {
System.out.println("Proses
menampilkan");
}
}
);
}
/** Metode utama */
public static void main(String[]
args) {
JFrame frame = new
DemoListenerTakBernama();
frame.setTitle("DemoListenerTakBernama");
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
|
Gambar
3.8 Program menangani event dari
empat tombol
Program
menciptakan empat listener menggunakan kelas-kelas inner tak-bernama (baris
22-52). Tanpa menggunakan kelas inner tak-bernama, Anda harus menciptakan empat
kelas yang berbeda. Kelas inner tak-bernama bekerja sama dengan kelas inner
biasa.
Kelas
inner tak-bernama dikompilasi menjadi NamaKelasOuter$#.class,
dimana # dimulai dari 1 dan diinkremen setiap kali kompiler menemukan kelas
inner tak-bernama. Pada contoh ini, kelas inner tak-bernama dikompilasi menjadi
DemoListenerTakBernama$1.class,DemoListenerTakBernama$2.class,DemoListenerTakBernama$3.class,
dan DemoListenerTakBernama$4.class.
Daripada
menggunakan metode setSize() untuk
menetapkan ukuran frame, program menggunakan metode pack() (baris 61), yang secara otomatis mengubah ukuran frame
sesuai dengan ukuran komponen yang ditempatkan.
3.6
Cara Alternatif untuk Mendefinisikan Kelas Listener
Ada
beberapa cara mendefinisikan kelas listener. Sebagai contoh, Anda diminta untuk
menulis-ulang kode3.3 dengan menciptakan hanya satu listener, meregistrasi
listener dengan tombol-tombol, dan mengijinkan listener untuk mendeteksi sumber
event, misalnya tombol memicu event, seperti ditampilkan pada kode3.4.
Kode3.4 DemoDeteksiSumber.java
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
|
import javax.swing.*;
import java.awt.event.*;
public class DemoDeteksiSumber extends JFrame {
// Menciptakan empat tombol
private JButton jbtBaru = new
JButton("Baru");
private JButton jbtBuka = new
JButton("Buka");
private JButton jbtSimpan = new
JButton("Simpan");
private JButton jbtTampil = new
JButton("Tampil");
public DemoDeteksiSumber() {
// Menciptakan suatu panel untuk memuat
tombol-tombol
JPanel panel = new JPanel();
panel.add(jbtBaru);
panel.add(jbtBuka);
panel.add(jbtSimpan);
panel.add(jbtTampil);
add(panel);
// Menciptakan suatu listener
ButtonListener listener = new
ButtonListener();
// Registrasi listener dengan
tombol-tombol
jbtBaru.addActionListener(listener);
jbtBuka.addActionListener(listener);
jbtSimpan.addActionListener(listener);
jbtTampil.addActionListener(listener);
}
class ButtonListener implements
ActionListener {
public void
actionPerformed(ActionEvent e) {
if (e.getSource() == jbtBaru)
System.out.println("Proses
Baru");
else if (e.getSource() == jbtBuka)
System.out.println("Proses
Buka");
else
if (e.getSource() == jbtSimpan)
System.out.println("Proses
Simpan");
else
if (e.getSource() == jbtTampil)
System.out.println("Proses
Tampil");
}
}
/** Metode utama */
public static void main(String[]
args) {
JFrame frame = new
DemoDeteksiSumber();
frame.setTitle("DemoDeteksiSumber");
frame.setLocationRelativeTo(null);
// Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
|
Program
ini hanya mendefinisikan satu kelas listener inner (baris 31-42), menciptakan
suatu listener dari kelas (baris 22), dan meregistrasikannya kepada empat
tombol (baris 25-28). Ketika suatu tombol diklik, tombol memicu suatu ActionEvent dan memanggil metode actionPerformed dari listener. Metode actionPerformed memeriksa sumber event menggunakan
metode getSource() untuk event
(baris 33, 35, 37, dan 39) dan menentukan tombol mana yang memicu event
terkait. Anda juga bisa menulis-ulang kode3.3 dengan mendefinisikan kelas frame
yang mengimplementasikan ActionListener,
seperti ditunjukkan pada kode3.5.
Kode3.5 DemoListenerSebagaiFrame.java
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
|
import javax.swing.*;
import java.awt.event.*;
public class DemoListenerSebagaiFrame extends JFrame
implements ActionListener {
//
Menciptakan empat tombol
private
JButton jbtBaru = new JButton("Baru");
private JButton jbtBuka = new
JButton("Buka");
private JButton jbtSimpan = new
JButton("Simpan");
private JButton jbtTampil = new
JButton("Tampil");
public DemoListenerSebagaiFrame() {
// Menciptakan suatu panel untuk memuat
tombol-tombol
JPanel panel = new JPanel();
panel.add(jbtBaru);
panel.add(jbtBuka);
panel.add(jbtSimpan);
panel.add(jbtTampil);
add(panel);
// Registrasi listener dengan
tombol-tombol
jbtBaru.addActionListener(this);
jbtBuka.addActionListener(this);
jbtSimpan.addActionListener(this);
jbtTampil.addActionListener(this);
}
// Mengimplementasikan metode
actionPerformed
public
void actionPerformed(ActionEvent e) {
if (e.getSource() == jbtBaru)
System.out.println("Proses Baru");
else
if (e.getSource() == jbtBuka)
System.out.println("Proses Buka");
else
if (e.getSource() == jbtSimpan)
System.out.println("Proses
Simpan");
else
if (e.getSource() == jbtTampil)
System.out.println("Proses
Tampil");
}
/** Metode utama */
public static void main(String[]
args) {
JFrame frame = new
DemoListenerSebagaiFrame();
frame.setTitle("DemoListenerSebagaiFrame");
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
|
Kelas
frame mewarisi JFrame dan
mengimplementasikan ActionListener
(baris 5). Jadi kelas tersebut adalah kelas listener untuk event-event aksi. Listener
diregistrasi dengan empat tombol (baris 23-26). Ketika suatu tombol diklik,
tombol tersebut memicu suatu ActionEvent
dan memanggil metode actionPerformed
dari listener. Metode actionPerformed
memeriksa sumber event menggunakan metode getSource()
untuk event (baris 31, 35, dan 37) dan menentukan tombol mana yang memicu
event.
3.7
Masalah: Kalkulator Hutang
Sekarang
Anda dapat menulis program untuk kalkulator hutang. Berikut adalah
langkah-langkah utama program:
1. Menciptakan
suatu antarmuka pengguna, seperti tertampil pada Gambar 3.9.
a)
Menciptakan suatu panel GridLayout
dengan 5 baris dan 2 kolom. Tambahkan label dan bidang teks ke dalam panel.
Tetapkan judul “Masukkan jumlah pinjaman, suku bunga, dan jumlah tahun”pada
panel.
b)
Menciptakan suatu panel lain dengan FlowLayout(FlowLayout.RIGHT)
dan tambahkan suatu tombol ke dalam panel.
c)
Menempatkan panel pertama ke tengah frame dan panel kedua ke bagian
selatan frame.
2.
Memproses event.
Menciptakan dan meregistrasi listener untuk memproses
event aksi pengklikan tombol. Handler kemudian memperoleh masukan pengguna
untuk pinjaman, suku bunga, dan jumlah tahun, menghitung pembayaran bulanan dan
pembayaran total, dan menampilkan nilai-nilai di dalam bidang-bidang teks.
Gambar
3.9 Program menghitung pembayaran
hutang
Program
utuh ditampilkan pada kode3.6.
Kode3.6 KalkulatorHutang.java
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
|
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
public class KalkulatorHutang extends JFrame {
// Menciptakan bidang teks untuk suku bunga,
// tahun, jumlah pinjaman, pembayaran
bulanan, dan pembayaran total
private JTextField
jtfSukuBungaTahunan = new JTextField();
private JTextField jtfJumlahTahun = new
JTextField();
private JTextField jtfJumlahPinjaman
= new JTextField();
private JTextField
jtfPembayaranBulanan = new JTextField();
private JTextField jtfPembayaranTotal
= new JTextField();
// Menciptakan suatu tombol Hitung
Pembayaran
private JButton jbtHitungHutang = new
JButton("Hitung Pembayaran");
public
KalkulatorHutang() {
// Panel p1 untuk memua label dan bidang
teks
JPanel p1 = new JPanel(new GridLayout(5, 2));
p1.add(new JLabel("Suku
Bunga Tahunan"));
p1.add(jtfSukuBungaTahunan);
p1.add(new JLabel("Jumlah
Tahun"));
p1.add(jtfJumlahTahun);
p1.add(new JLabel("Jumlah
Pinjaman"));
p1.add(jtfJumlahPinjaman);
p1.add(new JLabel("Pembayaran
Bulanan"));
p1.add(jtfPembayaranBulanan);
p1.add(new JLabel("Pembayaran
Total"));
p1.add(jtfPembayaranTotal);
p1.setBorder(new
TitledBorder("Masukkan
jumlah pinjaman, suku bunga, dan jumlah tahun"));
// Panel p2 untuk memuat tombol
JPanel p2 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
p2.add(jbtHitungHutang);
// Menambah panel ke frame
add(p1, BorderLayout.CENTER);
add(p2, BorderLayout.SOUTH);
// Register listener
jbtHitungHutang.addActionListener(new ButtonListener());
}
/** Menangani tombol Hitung Pembayaran */
private class ButtonListener implements ActionListener {
public void
actionPerformed(ActionEvent e) {
// Mendapatkan nilai-nilai dari bidang
teks
double bunga =
Double.parseDouble(jtfSukuBungaTahunan.getText());
int tahun =
Integer.parseInt(jtfJumlahTahun.getText());
double jumlahPinjaman =
Double.parseDouble(jtfJumlahPinjaman.getText());
// Menciptakan suatu objek hutang
Hutang hutang = new Hutang(bunga, tahun, jumlahPinjaman);
// Menghitung pembayaran bulanan dan
pembayaran total
jtfPembayaranBulanan.setText(String.format("%.2f",
hutang.dapatPembayaranBulanan()));
jtfPembayaranTotal.setText(String.format("%.2f",
hutang.dapatPembayaranTotal()));
}
}
public static void main(String[]
args) {
KalkulatorHutang frame = new
KalkulatorHutang();
frame.pack();
frame.setTitle("KalkulatorHutang");
frame.setLocationRelativeTo(null); // Pusat
frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
|
Hutang.java
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
|
public class Hutang {
private
double sukuBungaTahunan;
private int jumlahTahun;
private double jumlahPinjaman;
private java.util.Date tanggalPinjaman;
/** Konstruktor Default */
public Hutang() {
this(2.5, 1, 1000);
}
/** Menciptakan suatu objek Hutang dengan
suku bunga tahunan,
jumlah tahun, dan jumlah pinjaman tertentu
*/
public Hutang(double
sukuBungaTahunan, int jumlahTahun,
double jumlahPinjaman){
this.sukuBungaTahunan =
sukuBungaTahunan;
this.jumlahTahun = jumlahTahun;
this.jumlahPinjaman = jumlahPinjaman;
tanggalPinjaman = new
java.util.Date();
}
/**
Mengembalikan sukuBungaTahunan */
public double
dapatSukuBungaTahunan() {
return sukuBungaTahunan;
}
/**
Menetapkan sukuBungaTahunan yang baru */
public void
tetapkanSukuBungaTahunan(double sukuBungaTahunan) {
this.sukuBungaTahunan =
sukuBungaTahunan;
}
/**
Mengembalikan jumlahTahun */
public int
dapatJumlahTahun() {
return
jumlahTahun;
}
/**
Menetapkan jumlahTahun yang baru */
public
void tetapkanJumlahTahun(int jumlahTahun) {
this.jumlahTahun
= jumlahTahun;
}
/**
Mengembalikan jumlahPinjaman */
public
double dapatJumlahPinjaman() {
return
jumlahPinjaman;
}
/**
Menetapkan jumlahPinjaman yang baru*/
public
void tetapkanJumlahPinjaman(double jumlahPinjaman) {
this.jumlahPinjaman
= jumlahPinjaman;
}
/** Menghitung
pembayaran bulanan */
public
double dapatPembayaranBulanan() {
double sukuBungaBulanan =
sukuBungaTahunan / 1200;
double
pembayaranBulanan = jumlahPinjaman * sukuBungaBulanan / (1 -
(Math.pow(1
/ (1 + sukuBungaBulanan), jumlahTahun * 12)));
return
pembayaranBulanan;
}
/**
Menghitung total pembayaran */
public
double dapatPembayaranTotal() {
double
pembayaranTotal = dapatPembayaranBulanan() * jumlahTahun * 12;
return
pembayaranTotal;
}
/**
Mengembalikan tanggal pinjaman */
public
java.util.Date dapatTanggalPinjaman() {
return
tanggalPinjaman;
}
}
|
Antarmuka
pengguna diciptakan di dalam konstruktor (baris 18-44). Tombol merupakan sumber
event. Suatu listener diciptakan dan diregistrasi dengan tombol (baris 43).
Kelas
listener (baris 47-66) mengimplementasikan metode actionPerformed. Ketika tombol diklik, metode actionPerformed dipanggil untuk mendapatkan suku bunga (baris 51),
jumlah tahun (baris 53), dan jumlah pinjaman (baris 55). Pemanggilan jtfSukuBungaTahunan.getText() akan
mengembalikan teks string di dalam bidang teks jtfSukuBungaTahunan. hutang
digunakan untuk menghitung pembayaran hutang. Pemanggilan hutang.dapatPembayaranBulanan() mengembalikan pembayaran bulanan.
Metode String.format menggunakan sintaks
seperti printf untuk memformat suatu
angka menjadi format yang diinginkan. Pemanggilan metode setText pada suatu bidang teks menetapkan nilai string pada bidang
bidang teks tersebut.
3.8
Event Jendela
Beberapa
bagian yang terdahulu membahas beberapa event aksi. Event-event lainnya dapat
diproses dengan cara yang sama. Bagian ini akan menyajikan contoh penanganan WindowEvent. Sembarang subkelas dari
kelas Window dapat memicu beberapa
event jendela berikut: Jendela dibuka, dicoba untuk ditutup, ditutup,
diaktivasi, dideaktivasi, diikonfikasi, dan dideikonifikasi. Program pada
kode3.7 menciptakan suatu frame, merespon event-event jendela, dan menampilkan
pesan untuk mengindikasikan event yang sedang terjadi. Gambar 3.10 menunjukkan
suatu contoh hasil keluaran program.
Gambar
3.10 Beberapa event jendela
ditampilkan pada konsol ketika Anda menjalankan program dari command prompt
Kode3.7 UjiEventJendela.java
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
|
import java.awt.event.*;
import javax.swing.JFrame;
public class UjiEventJendela extends JFrame {
public static void main(String[]
args) {
UjiEventJendela frame = new
UjiEventJendela();
frame.setSize(220, 80);
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("UjiEventJendela");
frame.setVisible(true);
}
public UjiEventJendela() {
addWindowListener(new WindowListener() {
/**
* Handler untuk event deikonifikasi jendela
*
Dipanggil ketika suatu jendela diubah dari keadaaan terminimisasi
*
menjadi keadaan normal.
*/
public void windowDeiconified(WindowEvent
event) {
System.out.println("Jendela
dideikonifikasi");
}
/**
*
Handler untuk event ikonifikasi jendela
*
Dipanggil ketika suatu jendela diubah dari keadaan normal
*
menjadi keadaan terminimisasi. Pada banyak
platform, jendela terminimisasi
*
ditampilkan sebagai ikon tertentu pada properti
*
iconImage jendela.
*/
public void windowIconified(WindowEvent
event) {
System.out.println("Jendela
diikonifikasi");
}
/**
*
Handler untuk event aktifasi jendela
*
Dipanggil ketika jendela ditetapkan menjadi jendela aktif
*
bagi pengguna, berarti bahwa jendela (atau salah satu dari
*
sub-subkomponennya) akan menerima event papankunci (keyboard).
*/
public void windowActivated(WindowEvent event) {
System.out.println("Jendela
diaktivasi");
}
/**
*
Handler untuk event deaktivasi jendela
*
Dipanggil ketika jendela tidak lagi menjadi jendela aktif
*
bagi pengguna, berarti bahwa event papankunci tidak lagi
*
dikirim kepada jendela atau sub-subkomponennya.
*/
public void
windowDeactivated(WindowEvent event) {
System.out.println("Jendela
dideaktivasi");
}
/**
* Handler untuk event pembukaan jendela
* Dipanggil saat pertama kali jendela
terlihat atau muncul.
*/
public void windowOpened(WindowEvent event) {
System.out.println("Jendela
dibuka");
}
/**
* Handler untuk event percobaan penutupan
jendela
* Dipanggil ketika pengguna mencoba
untuk menutup jendela
* dari menu sistem jendela. Jika
program tidak secara eksplisit
* menyembunyikan atau menutup jendela
pada saat memproses
* event ini, operasi penutupan jendela
akan dibatalkan.
*/
public void windowClosing(WindowEvent event) {
System.out.println("Jendela
akan ditutup");
}
/**
* Handler untuk event penutupan jendela
* Dipanggil ketika jendela telah
ditutup akibat hasil dari
* pemanggilan handler percobaaan
penutupan jendela.
*/
public void
windowClosed(WindowEvent event) {
System.out.println("Jendela
ditutup");
}
});
}
}
|
WindowEvent dapat
dipicu oleh kelas Window atau oleh
sembarang subkelas dari Window.
Karena JFrame merupakan subkelas
dari Window, maka JFrame dapat memicu WindowEvent.
UjiEventJendela
mewarisi JFrame dan
mengimplementasikan WindowListener.
Antarmuka WindowListener
mendefinisikan beberapa metode abstrak (windowActivated,
windowClosed, windowClosing, windowDeactivated,
windowDeiconified, windowIconified, windowOpened) untuk menangani event-event jendela ketika jendela
diaktivasi, ditutup, dicoba untuk ditutup, dideaktivasi, dideikonifikasi,
diikonifikasi, atau dibuka.
Ketika
suatu event jendela, seperti aktivasi, terjadi, metode windowActivated dipanggil. Anda bisa mengimplementasikan metode windowActivated dengan suatu respon
konkrit jika Anda menginginkan event terkait diproses.
3.9
Adapter Antarmuka Listener
Karena
metode-metode di dalam antarmuka WindowListener
adalah abstrak, Anda harus mengimplementasikan semua metode tersebut meskipun
program Anda tidak peduli tentang beberapa event yang ada. Untuk mengatasi
kelelahan tersebut, JAVA menyediakan beberapa kelas pendukung, yang disebut
dengan adapter, yang menyediakan implementasi-implementasi default untuk semua
metode di dalam antarmuka listener. Implementasi default hanya berupa tubuh
kosong. JAVA menyediakan adapter listener untuk setiap antarmuka listener AWT
dengan beberapa handler. Adapter-adapter tersebut dinamai XAdapter untuk XListener.
Sebagai contoh, WindowAdapter adalah
adapter listener untuk WindowListener.
Tabel 3.3 mencantumkan beberapa adapter yang sering dijumpai.
Tabel
3.3 Beberapa Adapter Penting
Adapter
|
Antarmuka
|
WindowAdapter
MouseAdapter
MouseMotionAdapter
KeyAdapter
ContainerAdapter
ComponentAdapter
FocusAdapter
|
WindowListener
MouseListener
MouseMotionListener
KeyListener
ContainerListener
ComponentListener
FocusListener
|
Dengan
menggunakan WindowAdapter, contoh
terdahulu dapat disederhanakan seperti ditampilkan pada kode3.8, jika Anda
hanya tertarik pada event jendela. Kelas WindowAdapter
digunakan untuk menciptakan suatu listener tak-bernama, bukan WindowListener (baris 15). Handler windowActivated diimplementasikan pada
baris 16.
Kode3.8 DemoAdapter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import java.awt.event.*;
import javax.swing.JFrame;
public class DemoAdapter extends JFrame {
public static void main(String[]
args) {
DemoAdapter frame = new
DemoAdapter();
frame.setSize(220, 80);
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("DemoAdapter");
frame.setVisible(true);
}
public DemoAdapter() {
addWindowListener(new
WindowAdapter() {
public void
windowActivated(WindowEvent event) {
System.out.println("Jendela
diaktivasi");
}
});
}
}
|
3.10
Event Mouse
Suatu
event mouse dipicu manakala mouse ditekan, dilepas, diklik, digerakkan, digeret
pada suatu komponen. Objek MouseEvent
menangkap event tersebut, seperti jumlah klik yang terkait atau lokasi
(koordinat x dan y) dari mouse, seperti ditampilkan pada
Gambar 3.11.
Karena
kelas MouseEvent mewarisi InputEvent, Anda dapat menggunakan
metode-metode yang didefinisikan di dalam kelas InputEvent pada objek MouseEvent.
Kelas java.awt.Point merepresentasikan titik
pada suatu komponen. Kelas ini memuat dua variabel, x dan y, yang
merepresentasikan koordinat. Untuk menciptakan suatu Point, digunakan konstruktor berikut:
Point(int
x, int y)
Konstruktor
ini menciptakan suatu objek Point
dengan koordinat x dan y tertentu. Normalnya, bidang-bidang
data dalam suatu kelas dideklarasikan privat, tetapi pada kelas Point ini, dua bidang data
dideklarasikan publik.
JAVA
menyediakan dua antarmuka listener, MouseListener
dan MouseMotionListener, untuk
menangani event-event mouse, seperti ditunjukkan pada Gambar 3.12. Antarmuka MouseListener diimplementasikan untuk
memproses event-event, seperti aksi menekan, melepas, memasukkan, mengeluarkan,
atau mengklik mouse, dan MouseMotionListener
diimplementasikan untuk memproses event-event, seperti aksi menggeret atau
menggerakkan mouse.
Gambar
3.11 Kelas MouseEvent mengenkapsulasi informasi untuk event-event mouse
3.10.1
Contoh: Menggerakkan Pesan Pada Panel Dengan Mouse
Contoh
ini akan menyajikan suatu program yang menampilkan pesan di dalam suatu panel,
seperti tertampil pada Gambar 3.9. Anda dapat menggunakan mouse untuk
menggerakkan pesan. Pesan bergerak bila digeret oleh mouse dan selalu ditampilkan
pada ujung penunjuk mouse. Hasil keluaran program ditampilkan pada Gambar 3.13.
Gambar
3.12 Antarmuka MouseListener menangani saat mouse ditekan, dilepas,
Gambar
3.13 Anda bisa memindahkan pesan
dengan cara menggeret mouse
Kode3.9 DemoGerakPesan.java
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
|
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DemoGerakPesan extends JFrame {
public DemoGerakPesan() {
// Menciptakan suatu instans
PanelGerakPesan untuk memindahkan pesan
PanelGerakPesan p = new PanelGerakPesan
("JAVA itu Tangguh!");
// Menempatkan panel pesan di dalam frame
setLayout(new
BorderLayout());
add(p);
}
/** Metode utama */
public static void main(String[]
args) {
DemoGerakPesan frame = new
DemoGerakPesan();
frame.setTitle("DemoGerakPesan");
frame.setSize(200, 100);
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
// Kelas inner: PanelGerakPesan menggambar
pesan
static class
PanelGerakPesan extends JPanel {
private String pesan = "JAVA
itu Tangguh!";
private int x = 20;
private int y = 20;
/**
Menciptakan suatu panel untuk menggambar string s */
public
PanelGerakPesan(String s) {
pesan
= s;
addMouseMotionListener(new
MouseMotionAdapter() {
/**
Menangani event penggeretan mouse */
public void mouseDragged(MouseEvent e) {
// Mendapatkan lokasi baru dan menggambar
di layar
x = e.getX();
y = e.getY();
repaint();
}
});
}
/**
Menggambar komponen */
protected
void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString(pesan,
x, y);
}
}
}
|
Kelas PanelGerakPesan mewarisi JPanel untuk menggambarkan suatu pesan
(baris 27). Kelas tersebut menampilkan-ulang pesan ulang ketika pesan digeret
menggunakan mouse.Kelas ini didefinisikan di dalam sebagai kelas inner di dalam
kelas main karena hanya digunakan di dalam kelas tersebut. Dan lagi, kelas
inner tersebut didefinisikan statik karena tidak mereferensi sembarang anggota
instans dari kelas main.
Antarmuka
MouseMotionListener memuat dua
handler, mouseMoved dan mouseDragged, untuk menangani
event-event pergerakan mouse. Ketika Anda menggerakkan mouse dengan tombol
ditekan, metode mouseDragged
dipanggil untuk menggambar-ulang layar dan menampilkan pesan pada ujung
penunjuk mouse. Ketika Anda menggerakkan mouse tanpa menekannya, metode mouseMoved dipanggil.
Karena
listener hanya tertarik pada event penggeretan mouse, listener kelas inner
tak-bernama mewarisi MouseMotionAdapter
untuk mengoverride metode mouseDragged.
Jika kelas inner mengimplementasikan antarmuka MouseMotionListener, maka Anda harus mengimplementasikan semua handler,
meskipun jika handler Anda tidak peduli dengan beberapa event.
Metode mouseDragged dipanggil ketika Anda
menggerakkan mouse dengan tombol ditekan. Metode ini mendapatkan lokasi mouse
menggunakan metode getX dan getY (baris 39-40) di dalam kelas MouseEvent. Lokasi tersebut menjadi
lokasi baru bagi pesan. Pemanggilan metode repaint()
(baris 41) menyebabkan paintComponent
menjadi dipanggil (baris 47), yang menampilkan pesan pada lokasi baru.
3.11
Event Kunci
Event
kunci memampukan penggunaan kunci-kunci untuk mengendalikan dan melakukan aksi
atau mendapatkan masukan dari papankunci. Event kunci dipicu ketika suatu kunci
ditekan, dilepas, atau diketik pada suatu komponen. Objek KeyEvent mendeskripsikan keadaan event (misalnya, kunci ditekan,
dilepas, atau diketikkan) dan nilai kunci, seperti ditampilkan pada Gambar
3.14. JAVA menyediakan antarmuka KeyListener
untuk menangani event-event kunci, seperti ditampilkan pada Gambar 3.15.
Gambar
3.14 Kelas KeyEvent mengenkapsulasi informasi tentang event-event kunci
Gambar
3.15 Antarmuka KeyListener menangani event kunci dilepas, ditekan, dan diketikkan
Handler keyPressed dipanggil ketika kunci
ditekan, handler keyReleased
dipangil ketika kunci dilepas, dan handler keyTyped
dipanggil ketika suatu karakter Unicode dientrikan. Jika suatu kunci tidak
memiliki Unicode (kunci fungsi, kunci pemodifikasi, kunci aksi, dan kunci
kendali), maka handler keyTyped
tidak akan dipanggil. Setiap event kunci memiliki karakter kunci terkait atau
kode kunci yang dikembalikan oleh metode getKeyChar()
atau getKeyCode(). Kode kunci adalah
konstanta yang didefinisikan di dalam Tabel 3.4.
Tabel
3.4 Konstanta-Konstanta Kunci
Konstanta
|
Deskripsi
|
Konstanta
|
Deskripsi
|
VK_HOME
VK_END
VK_PGUP
VK_PGDN
VK_UP
VK_DOWN
VK_LEFT
VK_RIGHT
VK_ESCAPE
VK_TAB
VK_CONTROL
|
Kunci Home
Kunci End
Kunci Page Up
Kunci Page
Down
Kunci
Up-Arrow
Kunci
Down-Arrow
Kunci
Left-Arrow
Kunci
Right-Arrow
Kunci Escape
Kunci Tab
Kunci Control
|
VK_SHIFT
VK_BACK_SPACE
VK_CAPS_LOCK
VK_NUM_LOCK
VK_ENTER
VK_UNDEFINED
VK_F1 sampai VK_F12
VK_0 sampai
VK_9
VK_A sampai
VK_Z
|
Kunci Shift
Kunci
Backspace
Kunci Caps
Lock
Kunci Num
Lock
Kunci Enter
Kunci tidak
dikenali
Kunci Fungsi
F1 sampai F12
Kunci angka 0
sampai 9
Kunci Huruf A
sampai Z
|
Untuk
event penekanan-kunci dan pelepasan-kunci, getKeyCode()
mengembalikan nilai seperti didefinisikan di dalam Tabel 3.4. Untuk event
pengetikan-kunci, metode getKeyCode()
mengembalikan VK_UNDEFINED,
sedangkan getKeyChar() mengembalikan
karakter yang dientrikan.
Program
pada kode3.10 menampilkan suatu karakter yang dientri oleh pengguna. Pengguna
dapat memindahkan karakter ke atas, ke bawah, ke kiri, dan ke kanan,
menggunakan kunci panah VK_UP, VK_DOWN, VK_LEFT, dan VK_RIGHT.
Gambar 3.16 menampilkan hasil keluaran program.
Gambar
3.16 Program merespon event kunci
dengan menampilkan suatu karakter dan menggerakkannya ke atas, ke bawah, ke
kiri, dan ke kanan
Kode3.10 DemoEventKunci.java
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
|
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DemoEventKunci extends JFrame {
private
PanelPapanKunci panelPapanKunci = new PanelPapanKunci();
/** Menginisialisasi */
public DemoEventKunci() {
// Menambahkan panel papankunci untuk menerima dan menampilkan
masukan pengguna
add(panelPapanKunci);
// Menetapkan fokus
panelPapanKunci.setFocusable(true);
}
/** Metode utama */
public static void main(String[] args) {
DemoEventKunci frame = new
DemoEventKunci();
frame.setTitle("DemoEventKunci");
frame.setSize(300, 300);
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
// Kelas inner: PanelPapanKunci untuk
menerima masukan kunci
static class
PanelPapanKunci extends JPanel {
private int x = 100;
private int y = 100;
private char karKunci = 'J'; //
Kunci default
public PanelPapanKunci() {
addKeyListener(new KeyAdapter() {
public
void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN: y += 10; break;
case KeyEvent.VK_UP: y -= 10; break;
case KeyEvent.VK_LEFT: x -= 10; break;
case KeyEvent.VK_RIGHT: x += 10; break;
default: karKunci = e.getKeyChar();
}
repaint();
}
});
}
/** Menggambar karakter */
protected void
paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(new Font("TimesRoman",
Font.PLAIN, 24));
g.drawString(String.valueOf(karKunci),
x, y);
}
}
}
|
Kelas PanelPapanKunci mewarisi JPanel untuk menampilkan suatu karakter
(baris 28). Kelas ini didefinisikan sebagai kelas inner di dalam kelas utama,
karena hanya digunakan di dalam kelas utama tersebut. Juga, kelas inner
tersebut didefinisikan statik, karena tidak mereferensi sembarang anggota
instans dari kelas main.
Karena
program memperoleh masukan dari papankunci, program akan merespon KeyEvent dan mewarisi KeyAdapter untuk menangani masukan
kunci (baris 34).
Ketika
suatu kunci ditekan, handler keyPressed
dipanggil. Program menggunakan e.getKeyCode()
untuk mendapatkan kode kunci dan e.getKeyChar()
untuk mendapatkan karakter untuk kunci. Ketika kunci non-panah ditekan,
karakter ditampilkan (baris 41). Ketika kunci panah ditekan, maka karakter
bergerak pada arah yang diindikasikan oleh kunci panah (baris 37-40).
Hanya
komponen yang fokus saja yang bisa menerima KeyEvent. Untuk membuat komponen menjadi fokus, properti isFocusable ditetapkan bernilai true (baris 14).
3.12
Animasi menggunakan Kelas Timer
Tidak
semua objek sumber merupakan komponen GUI. Kelas javax.swing.Timer adalah suatu komponen sumber yang memicu ActionEvent pada laju yang telah
ditetapkan. Gambar 3.17 mencantumkan beberapa metode di dalam kelas ini.
Gambar
3.17 Suatu objek Timer memicu ActionEvent
pada laju tetap
Objek Timer berperan sebagai sumber suatu ActionEvent. Listener harus merupakan
instans dari ActionListener dan
diregistrasi dengan suatu objek Timer.
Anda dapat menciptakan objek Timer
menggunakan konstruktornya dengan suatu tunda dan suatu listener, dimana delay menspesifikasi jumlah milidetik
di antara dua event aksi. Anda dapat menambahkan listener tambahan menggunakan
metode addActionListener dan
mengubah delay menggunakan metode setDelay. Untuk memulai timer, metode start() perlu dipanggil. Untuk
menghentikan timer, metode stop()
perlu dipanggil.
Kelas Timer dapat digunakan untuk
mengendalikan animasi. Sebagai contoh, Anda dapat menggunakannya untuk
menampilkan suatu pesan bergerak, seperti yang tertampil pada Gambar 3.18,
dengan kode3.11.
Kode3.11 DemoAnimasi.java
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
|
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DemoAnimasi extends JFrame {
public DemoAnimasi() {
// Menciptakan suatu PanelPesanBergerak untuk menampilkan suatu
pesan bergerak
add(new PanelPesanBergerak("Pesan
bergerak?"));
}
/** Metode utama */
public static void main(String[]
args) {
DemoAnimasi frame = new
DemoAnimasi();
frame.setTitle("DemoAnimasi");
frame.setSize(280, 100);
frame.setLocationRelativeTo(null);
// Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
// Kelas inner: Menampilkan suatu pesan
bergerak
static class
PanelPesanBergerak extends JPanel {
private String pesan = "JAVA
itu Tangguh!";
private int xKoordinat = 0;
private int yKoordinat = 20;
public PanelPesanBergerak(String
pesan) {
this.pesan = pesan;
// Menciptakan suatu timer
Timer timer = new Timer(1000, new TimerListener());
timer.start();
}
/** Menggambar pesan */
protected void
paintComponent(Graphics g) {
super.paintComponent(g);
if (xKoordinat > getWidth()) {
xKoordinat = -20;
}
xKoordinat += 5;
g.drawString(pesan, xKoordinat,
yKoordinat);
}
class TimerListener implements ActionListener {
/** Menangani ActionEvent */
public void actionPerformed(ActionEvent e) {
repaint();
}
}
}
}
|
Kelas PanelPesanBergerak mewarisi JPanel untuk menampilkan suatu pesan
(baris 22). Kelas ini didefinisikan sebagai kelas inner di dalam kelas utama, karena
hanya digunakan di dalam kelas utama tersebut saja. Dan, kelas inner tersebut
didefinisikan statik, karena tidak mereferensi sembarang anggota instans dari
kelas utama.
Suatu
listener kelas inner didefinisikan pada baris 46 untuk merespon ActionEvent. Baris 31 menciptakan suatu
Timer untuk listener tersebut. Timer
dimulai pada baris 32 dan memicu suatu ActionEvent
setiap detik, dan listener meresponnya pada baris 49 untuk menggambar-ulang
panel. Ketika panel digambar, koordinat x diinkremen (baris 42), sehingga pesan
ditampilkan ke kanan. Ketika koordinat x melebihi batas panel, maka koordinat x
ditetapkan-ulang menjadi -20 (baris 40), sehingga pesan terus bergerak dari
kiri ke kanan.
Pada
kode3.12 akan didemonstrasikan mendesain program untuk menggambarkan jam yang
sedang berdetak. Apa yang Anda lakukan agar jam menampilkan suatu waktu
sekarang yang baru pada setiap detik? Untuk membuat jam berdetak setiap detik,
Anda harus menggambarkan-ulang jam tersebut setiap detik dengan waktu sekarang
yang terperbarui. Anda bisa menggunakan suatu timer untuk mengendalikan
penggambaran-ulang jam.
Kode3.12 AnimasiJam.java
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
|
import java.awt.event.*;
import javax.swing.*;
public class AnimasiJam extends JFrame {
private JamDiam jam = new
JamDiam();
public AnimasiJam() {
add(jam);
// Menciptakan suatu timer dengan tunda
1000 ms
Timer timer = new Timer(1000, new TimerListener());
timer.start();
}
private class TimerListener implements ActionListener {
/** Menangani event aksi */
public void actionPerformed(ActionEvent e) {
// Menetapkan waktu baru dan menggambar-ulang jam, menampilkan
waktu sekarang
jam.tetapkanWaktuSekarang();
jam.repaint();
}
}
/** Metode utama */
public static void main(String[]
args) {
JFrame frame = new AnimasiJam();
frame.setTitle("AnimasiJam");
frame.setSize(200, 200);
frame.setLocationRelativeTo(null); //
Pusat frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
|
Program
menampilkan suatu jam yang berdetak, seperti tertampil pada Gambar 3.19. Kelas AnimasiJam menciptakan JamDiam (baris 5). Baris 11 menciptakan
Timer untuk AnimasiJam. Timer dimulai pada baris 12. Timer memicu suatu ActionEvent setiap detik, dan listener
merespon untuk menetapkan suatu waktu baru (baris 19) dan menggambar-ulang jam
(jam 20). Metode setCurrentTime()
yang didefinisikan di dalam JamDiam
menetapkan waktu sekarang di dalam jam.
Gambar
3.19 Suatu jam berdetak ditampilkan di
dalam panel
No comments:
Post a Comment