Komponen antarmuka tanpa data hanyalah gambar statis — nilai dari app muncul ketika data mengalir dari komponen ke logika, diproses, lalu dialirkan kembali ke komponen lain. Chapter ini membahas penampung data di dalam app (properti), alur baca-proses-tulis, penanganan state saat pemrosesan berjalan, dan pemisahan logika dari UI — fondasi yang membuat app bisa diuji. Cakupannya:
- properti class app sebagai state (
app.data,app.filename) - pola baca komponen → proses → tulis komponen
- transisi state: menonaktifkan komponen saat pemrosesan
- pemisahan pola model–view dan logika yang teruji
Properti App sebagai State #
Data app yang hidup lebih lama dari satu callback harus punya tempat tinggal resmi: properti class. Kita sudah melihatnya menyimpan komponen; bagian data tinggal menempel di blok yang sama:
properties (Access = public)
UIFigure matlab.ui.Figure
EditField matlab.ui.control.NumericEditField
LabelHasil matlab.ui.control.Label
dataPath char = 'data_cuaca.csv' % berkas data aktif
dataTable double = [] % data hasil muat
hasil struct = struct() % hasil analisis terakhir
endMari kita bedah baris-baris kode di atas:
- Baris 2-4: tiga properti komponen — dibuat dan dimusnahkan bersama app.
- Baris 6-8 (
dataPath,dataTable,hasil): state aplikasi — data yang dipakai lintas callback; tanpa properti ini, setiap callback harus menghitung ulang atau saling melempar variabel lokal. - Baris 6 (
char+ nilai awal): tipe dan nilai bawaan properti dideklarasikan sekaligus — pola yang sama dengan materi OOP.
Aturan pentingnya: satu sumber kebenaran. Jika dataTable adalah data resmi app, semua callback membaca dari sana — tidak ada callback yang diam-diam menyimpan salinannya sendiri, karena dua salinan pasti berpisah nilainya.
Pola Baca → Proses → Tulis #
Alur standar hampir semua callback berbentuk tiga langkah: baca nilai dari komponen input, serahkan ke fungsi proses, tulis hasil ke komponen output:
function KonversiButtonPushed(app, event)
% Langkah 1: baca input dari komponen.
suhu = app.EditFieldSuhu.Value;
satuan = app.DropDownSatuan.Value;
% Langkah 2: proses di fungsi terpisah (bukan di sini).
[hasil, ok, pesan] = prosesForm( ...
struct('suhuTeks', num2str(suhu), 'satuan', satuan));
% Langkah 3: tulis hasil ke komponen output.
if ok
app.hasil = hasil;
app.LabelHasil.Text = hasil.labelTeks;
else
uialert(app.UIFigure, pesan, "Input Tidak Valid", Icon="warning");
end
endKetika callback di atas berjalan, hasil konversi tampil di label; jika input gagal divalidasi, dialog peringatan muncul di depan jendela app. Perhatikan pembagian kerjanya: callback tidak berisi satu rumus pun — komputasi ada di prosesForm(), dan fungsi itulah yang bisa diuji tanpa GUI (dibahas dua bagian di bawah).
Transisi State Saat Pemrosesan #
State app tidak hanya data hasil — kondisi antarmuka juga state. Pola yang lazim saat pemrosesan panjang: kunci pemicu, proses, pulihkan. app.ProsesButton.Enable = "off" mencegah klik ganda; label status berubah menjadi "Memproses..."; setelah selesai semuanya dikembalikan. Karena callback berjalan satu per satu di event loop, penonaktifan tombol adalah satu-satunya penjaga bahwa pemrosesan tidak tumpang tindih dengan dirinya sendiri.
Pembaruan banyak komponen sekaligus (label, tabel, ringkasan) tidak perlu trik khusus — cukup tulis properti-propertinya lalu biarkan MATLAB menggambar ulang jendela di kesempatan berikutnya; sisipkan drawnow bila kita ingin tampilan terbarui segera sebelum komputasi lanjut.
Menyimpan State Saat App Ditutup #
Data app lenyap saat objek app dihapus. Untuk preferensi atau data kerja, callback penutupan jendela adalah titik simpan terakhir:
function UIFigureCloseRequest(app, event)
% Dipanggil sebelum jendela benar-benar ditutup.
simpanPreferensi(app.dataPath, app.hasil);
delete(app)
endCallback CloseRequestFcn milik UIFigure dijalankan ketika pengguna menekan tombol tutup jendela — penutupan tidak terjadi otomatis; pemanggilan delete(app) yang mengakhirinya. Slot inilah tempat menulis preferensi, berkas kerja, atau konfirmasi “ada perubahan belum disimpan” sebelum app musnah.
Pemisahan Logika dari UI #
Pola model–view versi ringkas memetakan tiga peran dalam app kita:
| Peran | Di dalam app | Di luar app (teruji) |
|---|---|---|
| View | komponen: EditField, Label, UIAxes | — |
| Controller | callback: KonversiButtonPushed | contoh.m (alur simulasi) |
| Model | — | prosesForm(), analisisCuaca() |
Fungsi model menerima struct input dan mengembalikan struct hasil — tidak menyentuh satu komponen pun, tidak memanggil uialert, tidak membaca app. Konsekuensinya: fungsi model bisa diuji di Octave seperti fungsi biasa. Inilah isi inti contoh.m:
form = { ...
struct('suhuTeks', '25', 'satuan', 'Fahrenheit'), ...
struct('suhuTeks', '100', 'satuan', 'Kelvin'), ...
struct('suhuTeks', ' dua puluh ', 'satuan', 'Fahrenheit'), ...
struct('suhuTeks', '36.6', 'satuan', 'Reamur')};
for k = 1:numel(form)
fprintf('form %d: suhuTeks="%s" satuan="%s"\n', ...
k, form{k}.suhuTeks, form{k}.satuan);
[hasil, ok, pesan] = prosesForm(form{k});
if ok
fprintf(' -> Tulis komponen: Label.Text = "%s"\n', ...
hasil.labelTeks);
else
fprintf(' -> Tampilkan uialert: %s\n', pesan);
end
endMari kita bedah baris-baris kode di atas:
- Baris 1-5 (
form = {...}): empat kasus input dibungkus struct — dua valid, satu berisi teks dengan spasi tepi dan kata bukan angka, satu memakai satuan yang tidak dikenal. - Baris 7-10 (
for k = 1:numel(form)): loop memainkan peran callback yang dipicu berulang: baca input → panggilprosesForm()→ tulis keluaran. - Baris 11-17 (
if ok ... else ...): dua jalur keluaran persis seperti callback nyata — label diperbarui saat valid,uialertdigantifprintfsaat gagal.
Di dalam prosesForm() (berkas lengkap), fungsi mengerjakan tiga tahap bersih: sanitasi strtrim() + konversi str2double() dengan cek NaN, komputasi switch per satuan, lalu pembentukan labelTeks dengan sprintf() — semuanya tanpa menyentuh UI.
Output yang Dihasilkan:
form 1: suhuTeks="25" satuan="Fahrenheit"
-> Tulis komponen: Label.Text = "77.0 Fahrenheit"
form 2: suhuTeks="100" satuan="Kelvin"
-> Tulis komponen: Label.Text = "373.1 Kelvin"
form 3: suhuTeks=" dua puluh " satuan="Fahrenheit"
-> Tampilkan uialert: "dua puluh" bukan angka
form 4: suhuTeks="36.6" satuan="Reamur"
-> Tampilkan uialert: satuan "Reamur" tidak dikenalRingkasan #
Data app hidup di properti class (dataPath, dataTable, hasil) sebagai satu sumber kebenaran lintas callback. Alur callback mengikuti pola baca → proses → tulis: nilai komponen dibaca, komputasi didelegasikan ke fungsi model, hasil ditulis ke komponen output atau dilaporkan lewat uialert. State antarmuka (tombol nonaktif, label status) ikut dikelola saat pemrosesan berjalan, dan CloseRequestFcn menjadi titik simpan terakhir sebelum delete(app). Pemisahan model dari view dibuktikan di contoh.m: prosesForm() mengubah struct menjadi struct dan lolos uji Octave, sementara versi GUI-nya tinggal menempelkan fungsi itu ke callback.