Pendahuluan
Pada pemrograman berbasis GUI [1], ketika kita melakuan suatu perubahan terhadap widget, terkadang kita ingin memberi tahu widget lain bahwa widget tertentu telah berubah. Secara lebih umum, kita ingin agar satu object dengan object lain bisa berkomunikasi. Contohnya, ketika user mengklik tombol Close, maka ketika itu fungsi untuk menutup window akan dipanggil.
Kebanyakan dari GUI toolkit teknologi lama, untuk mengatasi event listener, kita harus menggunakan callback. Yaitu mengarahkan suatu fungsi tertentu kepada suatu event. Sehingga ketika event di-trigger, sistem akan memanggil fungsi yang telah kita arahkan sebelumnya. Namun pada PySide (lebih tepatnya Qt), kita menggunakan konsep signal dan slots.
Signals dan Slots
Pada Qt, kita memiliki cara alternatif dari pada teknik callback; yaitu signals dan slots [2]. Sebuah signal akan dipicu ketika suatu event tertentu terjadi. Qt’s widgets memiliki banyak signals yang sudah terdefinsikan. Akan tetapi kita tetap bisa menambahkan signals sesuka kita dengan cara membuat sub-class-nya. Ada pun slot, ia adalah sebuah fungsi yang akan dipanggil sebagai response dari signal yang ter-trigger.
Contoh Signal dan Slot
Dalam tutorial pyside kali ini, saya akan mencontohkan penggunakan signal dan slot pada kelas PySide.QtGui.QLineEdit
. Pada QLineEdit
, terdapat 6 buah signal. Yaitu [3]:
cursorPositionChanged(arg1, arg2)
editingFinished()
returnPressed()
selectionChanged()
textChanged(arg1)
textEdited(arg1)
Buat window dari kelas QtGui.QWidget
.
window = QtGui.QWidget()
window.resize(400, 130)
window.setWindowTitle('Tutorial PySide')
Buat label dan layout.
namaLabel = QtGui.QLabel('Nama')
namaEdit = QtGui.QLineEdit()
hasilLabel = QtGui.QLabel('Hasil: ')
layout = QtGui.QGridLayout(window)
layout.addWidget(namaLabel, 0, 0)
layout.addWidget(namaEdit, 1, 0)
layout.addWidget(hasilLabel, 2, 0)
Tampilkan window.
window.show()
Hubungkan slot dengan signal
Buat sebuah fungsi sebagai slot (yaitu fungsi yang akan dipanggil ketika signal ter-trigger).
def onNamaEditTextChanged():
hasilLabel.setText(
'Hasil: <strong style="color: red">' + namaEdit.text() + '</strong>'
)
Fungsi di atas akan mengubah text dari widget hasilLabel
dan mengisinya dengan isi dari input namaEdit
.
Hubungkan fungsi di atas dengan signal textChanged
. Sehingga ketika kita mengganti teks pada inputan namaEdit
, fungsi di atas akan dieksekusi.
namaEdit.textChanged.connect(onNamaEditTextChanged)
Custom Signal dan Slot
Pertama, pada PySide sudah menyediakan kelas Signal
. Yaitu pada package QtCore.Signal
. Kedua, signal tidak perlu harus terikat pada suatu kelas tertentu. Artinya kita bisa membuat signal langsung secara mandiri tanpa harus menjadi attribut dari kelas QtGui.QWidget
.
signal = QtCore.Signal()
signal.connect(fungsiTerserah)
...
...
...
signal.emit()
Pada kode di atas, kita membuat instance dari kelas QtCore.Signal
.
signal = QtCore.Signal()
Lalu kita menghubungkan signal tersebut dengan slot/fungsi tertentu dengan memanggil fungsi signal.connect(slot)
.
Maka ketika signal.emit()
dipanggil, slot yang sudah didaftarkan pada fungsi connect
akan dipanggil.
Contoh Custom Signal dan Slot
Buat kelas dengan nama Kakek
sebagai kelas turunan dari QtCore.QObject
.
class Kakek (QtCore.QObject):
telahDatang = QtCore.Signal()
def __init__(self):
super(Kakek, self).__init__()
def datang (self):
print("Kakek telah datang...")
self.telahDatang.emit()
Pada kode di atas, saya membuat satu signal baru, dengan nama telahDatang
. Dan signal telahDatang
akan di-emmit setelah fungsi datang()
dieksekusi.
Buat instance dari kelas Kakek
.
kakek = Kakek()
Buat fungsi sebagai slot yang akan kita hubungkan dengan signal kakek.telahDatang
.
def katakanHalo():
print("Halo kakek!")
Hubungkan slot dengan sgnal.
kakek.telahDatang.connect(katakanHalo)
Panggil fungsi datang()
, maka slot katakanHalo()
akan dipanggil setelah itu.
for i in range(10):
kakek.datang()
Output:
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kakek telah datang...
Halo kakek!
Kode Program Lengkap
Signal dan slot pada QLineEdit (versi prosedural)
import sys, time
from PySide import QtGui
"""
Jago Ngoding tutorial PySide bahasa Indonesia
author: Ibnu Jakaria
"""
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window.resize(400, 130)
window.setWindowTitle('Tutorial PySide')
namaLabel = QtGui.QLabel('Nama')
namaEdit = QtGui.QLineEdit()
hasilLabel = QtGui.QLabel('Hasil: ')
layout = QtGui.QGridLayout(window)
layout.addWidget(namaLabel, 0, 0)
layout.addWidget(namaEdit, 1, 0)
layout.addWidget(hasilLabel, 2, 0)
def onNamaEditTextChanged():
hasilLabel.setText(
'Hasil: <strong style="color: red">' + namaEdit.text() + '</strong>'
)
# menghubungakan signal dan slot
namaEdit.textChanged.connect(onNamaEditTextChanged)
window.show()
sys.exit(app.exec_())
Signal dan slot pada QLineEdit (versi OOP)
import sys, time
from PySide import QtGui
"""
Jago Ngoding tutorial PySide berbahasa Indonesia
author: Ibnu Jakaria
"""
class Jendela(QtGui.QWidget):
def __init__(self):
super(Jendela, self).__init__()
self.siapkanUI()
self.siapkanListener()
def siapkanUI(self):
self.resize(400, 130)
self.setWindowTitle('Tutorial PySide')
self.namaLabel = QtGui.QLabel('Nama')
self.namaEdit = QtGui.QLineEdit()
self.hasilLabel = QtGui.QLabel('Hasil: ')
self.layout = QtGui.QGridLayout(self)
self.layout.addWidget(self.namaLabel, 0, 0)
self.layout.addWidget(self.namaEdit, 1, 0)
self.layout.addWidget(self.hasilLabel, 2, 0)
def siapkanListener(self):
self.namaEdit.textChanged.connect(self.onNamaEditTextChanged)
def onNamaEditTextChanged(self):
self.hasilLabel.setText(
'Hasil: <strong style="color: red">' + self.namaEdit.text() + '</strong>'
)
app = QtGui.QApplication(sys.argv)
jendela = Jendela()
jendela.show()
sys.exit(app.exec_())
Custom signal dan slot
from PySide import QtGui, QtCore
"""
Jago Ngoding tutorial PySide bahasa Indonesia
author: Ibnu Jakaria
"""
class Kakek (QtCore.QObject):
telahDatang = QtCore.Signal()
def __init__(self):
super(Kakek, self).__init__()
def datang (self):
print("Kakek telah datang...")
self.telahDatang.emit()
kakek = Kakek()
def katakanHalo():
print("Halo kakek!")
kakek.telahDatang.connect(katakanHalo)
for i in range(10):
kakek.datang()
Demikian tutorial kali ini, semoga bermanfaat~
Referensi:
[1] “Signals & Slots”, Qt 4.8, http://doc.qt.io/qt-4.8/signalsandslots.html#introduction, diakses tanggal 05 Oktober 2017.
[2] “Signals & Slots”, Qt 4.8, http://doc.qt.io/qt-4.8/signalsandslots.html#signals-and-slots, diakses tanggal 05 Oktober 2017
[3] “QLineEdit”, PySide documentation v1.07, https://srinikom.github.io/pyside-docs/PySide/QtGui/QLineEdit.html, diakses tanggal 05 Oktober 2017