10. Arayüz (GUI) uygulaması
Pencereli uygulamalar pencere bloğuyla yazılır. Arayüz bildirimseldir:
ne görüneceğini yazarsınız, nasıl çizileceğini dil halleder.
Bu sayfadaki örnekler belge testinde derlenir ama çalıştırılmaz — pencere açmak ekran gerektirir. Derlenmeleri, yazılanların gerçekten geçerli olduğunu gösterir.
⚠️ Arayüz uygulamaları sistemin arayüz kütüphanelerini kullanır (KabaOS'ta kurulu gelir). Konsol/servis/web programları bunlara ihtiyaç duymaz.
Hazır iskelet: kabalang yeni <ad> --gui
(13. sayfa).
En küçük pencere
kullan kaba.arayuz
pencere AnaPencere:
baslik = "KabaOS Hoş Geldiniz"
genislik = 400
yukseklik = 250
etiket AdEtiketi:
metin = "Lütfen adınızı girin:"
girdi AdGirdisi:
ipucu = "Buraya yazın..."
dugme SelamDugmesi:
metin = "Selam Ver"
tiklandiginda:
eger AdGirdisi.metin == "":
mesaj_kutusu("Hata", "Lütfen önce adınızı yazın!")
degilse:
mesaj_kutusu("Merhaba", "Hoş geldin " + AdGirdisi.metin + "!")Yapı şudur:
pencere Ad:— pencerenin kendisi;baslik,genislik,yukseklik,tema,simgeözellikleri.- İçeride bileşenler:
tur Ad:ve altında özellikleri. - Bileşenin altında olay bloğu:
tiklandiginda:vb. Gövdesi sıradan KabaLang kodudur. - Bileşene başka yerden
Ad.ozellikdiye erişilir (AdGirdisi.metin,DurumCubugu.deger).
Bileşenler
Dilin tanıdığı 15 bileşen türü:
| Bileşen | Ne işe yarar |
|---|---|
etiket |
salt okunur yazı |
dugme |
tıklanabilir düğme |
girdi |
tek satırlık metin kutusu |
metin_alani |
çok satırlı metin kutusu |
onay_kutusu |
işaret kutusu (secili) |
acilir_liste |
açılır seçim kutusu |
liste · tablo · agac |
liste / tablo / ağaç görünümü |
ilerleme_cubugu |
yüzde göstergesi (deger) |
kaydirici |
sürgü |
grafik |
canlı çizgi grafiği |
resim |
görsel |
sekme_kutusu |
sekmeli kap (sekme "Ad":) |
durum_cubugu |
pencere altı durum satırı |
Olaylar dört tanedir: tiklandiginda · degistiginde ·
cift_tiklandiginda · secildiginde.
⚠️ Tanımadığı bir özelliği yazarsanız derleyici onu okumaz. Örneğin
gorunur / etkin diye bir özellik yoktur (ölçüldü) — yazarsanız
hiçbir şey olmaz. Mantık değerleri noktasız yazılır: secili = dogru.
Yerleşim: yatay_kutu / dikey_kutu
kullan kaba.arayuz
kullan kaba.sistem
pencere SistemPaneli:
baslik = "Sistem Paneli"
genislik = 620
yukseklik = 420
tema = "koyu"
etiket BaslikEtiketi:
metin = "KabaOS Sistem Durumu"
stil = "font-size: 15px; font-weight: bold; color: #7aa2f7;"
yatay_kutu ButonSatiri:
dugme CekirdekBtn:
metin = "Çekirdek Bilgisi"
tiklandiginda:
SonucKutusu.metin = sistem.komut("uname -srm")
DurumCubugu.deger = 50
dugme TemizleBtn:
metin = "Temizle"
tiklandiginda:
SonucKutusu.temizle()
DurumCubugu.deger = 0
ilerleme_cubugu DurumCubugu:
deger = 0
metin_alani SonucKutusu:
salt_okunur = dogruyatay_kutu bileşenleri yan yana, dikey_kutu alt alta dizer; iç içe
yazılabilirler.
Kart kutusu, yazı hizası, açılır listede sıra
yatay_kutu / dikey_kutu bir stil alabilir: zemin, kenarlık, köşe
yarıçapı ve dolgu kutunun arkasına çizilir — "kart" görünümü. Dolgu ve
kenarlık kalınlığı kutunun iç kenarı olur. Kutunun stili sabit metindir
(bağlanmaz, çalışırken yazılmaz); iki temada da okunsun diye yarı saydam renk
(rgba(…)) iyi sonuç verir. Kutunun başka özelliği okunmaz.
etiket stilinde text-align: left | center | right her satırı hizalar
(sayı sütunları sağa, rozet yazısı ortaya).
acilir_liste.secili_sira seçili öğenin sırasıdır (0'dan); okunur ve
yazılır — programdan seçim yapmanın yolu budur (aralık dışı değer yok sayılır).
kullan kaba.arayuz
pencere Kartlar:
baslik = "Kart"
genislik = 360
yukseklik = 220
dikey_kutu Kart:
stil = "background: rgba(127, 140, 160, 0.10); border: 1px solid rgba(127, 140, 160, 0.3); border-radius: 12px; padding: 14px;"
acilir_liste Secim:
secenekler = ["Bir", "İki", "Üç"]
etiket Sayi:
metin = "12,5 ms"
stil = "text-align: right;"
dugme SonBtn:
metin = "Sonuncuyu seç"
tiklandiginda:
Secim.secili_sira = 2
Sayi.metin = "sıra " + metin(Secim.secili_sira)Sekmeler ve zamanlayıcı
zamanlayici <süre>ms: bloğu belirtilen aralıkla kendiliğinden çalışır —
canlı gösterge yapmanın yolu budur.
kullan kaba.arayuz
kullan kaba.sistem
izinler:
ag_erisim = yanlis
pencere CanliPanel:
baslik = "Canlı Saat"
genislik = 460
yukseklik = 280
tema = "koyu"
sekme_kutusu AnaSekmeler:
sekme "Saat":
etiket SaatEtiketi:
metin = "00:00:00"
stil = "font-size: 34px; font-weight: bold; color: #9ece6a;"
sekme "Sistem":
etiket BellekEtiketi:
metin = "Bellek: —"
zamanlayici 1000ms:
SaatEtiketi.metin = zaman.saat()
BellekEtiketi.metin = "Bellek: " + sistem.bellek()izinler: — uygulamanın hak beyanı
Pencere dosyasının başındaki izinler: bloğu uygulamanın neye ihtiyacı
olduğunu bildirir; kabalang derle bu beyandan ikilinin yanına KabaOS
AppArmor profilini (<ikili>.apparmor) kendiliğinden yazar.
izinler:
ag_erisim = yanlis
dosya_yazma = "~/Belgeler"Blok pencere gövdesinin içine de yazılabilir; o zaman gövde bir
girinti daha derin olur.
Tanınan anahtarlar (kanonik küme: cekirdek/izin_denetimi.py,
IZIN_ANAHTARLARI):
| Anahtar | Değer | Ne yapar |
|---|---|---|
ag_erisim |
dogru / yanlis |
profildeki network inet kuralı |
surec_calistirma |
dogru / yanlis |
sistem.komut çağrılarının beyanı |
dis_cagri |
dogru / yanlis |
FFI (dis fonksiyon) — beyanı ZORUNLU |
dosya_yazma |
yol (~/... ya da /...) |
profildeki rw kuralının kökü |
Blok kuralları — hepsi derleme zamanında denetlenir:
- Gövdedeki her satır
anahtar = degerbiçimindedir. Başka bir satır derleme hatasıdır. ⚠️ Eskiden=içermeyen tek bir satır bloğu sessizce kapatıyor ve ondan sonraki bütün izinler AppArmor profiline hiç girmiyordu; derleme yine yeşil yanıyordu (ölçüldü 2026-09-26, kapıcekirdek/test_izinler_blogu.py). - Boş satır ve
#yorumu bloğu kapatmaz; gövdenin ortasına yazılabilir. - Bilinmeyen anahtar hatadır.
dosya_yazgibi bir yazım hatası eskiden sessizce yok sayılıyordu: kullanıcı istediği izni almadığını hiç öğrenmiyordu. - Mantıksal izinlerin değeri yalnız
dogruya dayanlisolabilir (tırnaklı yazım da geçerlidir:"yanlis").true·evet·1kabul edilmez — denetçi ile profil üreteci bu değerlerde birbirine zıt karar veriyordu. dosya_yazmamutlak ya da ev dizini yolu ister. ⚠️dosya_yazma = ""eskiden profile/** rw,yazıyordu — yani bütün dosya sistemine yazma hakkı, veapparmor_parsero profili geçerli buluyordu.dosya_yazma = yanlisise göreli bir yol üretip profili sözdizimsel olarak bozuyordu (profil hiç yüklenmiyor). İzin istemiyorsanız satırı silin,yanlisyazmayın.- Aynı anahtarı çelişkili iki değerle beyan etmek hatadır.
Hazır iletişim kutuları
kullan kaba.arayuz
pencere Kutular:
baslik = "İletişim kutuları"
genislik = 320
yukseklik = 180
dugme BilgiBtn:
metin = "Bilgi"
tiklandiginda:
mesaj_kutusu("Bilgi", "İşlem tamamlandı")
dugme UyariBtn:
metin = "Uyarı"
tiklandiginda:
uyari_kutusu("Uyarı", "Disk doluyor")
dugme HataBtn:
metin = "Hata"
tiklandiginda:
hata_kutusu("Hata", "Bağlantı kurulamadı")İkiz dosya mimarisi: ana.ui + ana.kbl
Büyüyen bir arayüzü koddan ayırabilirsiniz. Görsel tasarım .ui dosyasına,
davranış aynı adlı .kbl dosyasına yazılır; derleyici ikisini birleştirir.
Önce ana.ui:
```kabalang dosya:ana.ui pencere DemoPencere: baslik = "İkiz mimari" genislik = 480 yukseklik = 300 tema = "koyu"
etiket lbl_durum:
metin = "Sistem Durumu: Çevrimiçi"
dugme TestBtn:
metin = "Bildirim Gönder"
Sonra `ana.kbl` — yalnız olay işleyicileri:
```kabalang
kullan kaba.arayuz
kullan kaba.sistem
TestBtn.tiklandiginda:
sistem.bildirim("Demo", "Uygulama çalışıyor!")
lbl_durum.metin = "Son bildirim: " + zaman.saat()İki yön arasında geçiş komutları vardır:
| Komut | Ne yapar |
|---|---|
kabalang birlestir ana.kbl |
.ui içeriğini kaynağın içine alır (tek dosya) |
kabalang ayir ana.kbl |
Arayüzü kaynaktan .ui dosyasına çıkarır |
Canlı bağlama
Bir pencere: bloğu masaüstü uygulamasına derlenir. Özellik değerleri
bağlama olarak ele alınır: bir değer başka bir bileşenin özelliğine
dayanıyorsa, o özellik değiştiğinde kendiliğinden yenilenir.
2026-10-18:
--qml(Plasma apleti / QML penceresi çıktısı) kaldırıldı; tek çıktı LLVM ile derlenen yerel ikilidir.
ornekler/03-arayuz/07_canli_baglama.kbl bunu gösterir. Şu satır
etiket SelamEtiketi:
metin = "Merhaba " + AdGirdisi.metincanlıdır. Yani girdiye yazmak etiketi gerçekten değiştirir.
Bu 2026-09-26'da değişti. Öncesinde masaüstü çıktısı değeri yalnız kuruluş anında bir kez atıyordu ve bildirimsel özellikler donuk kalıyordu.
Hangi kaynaklar canlı — kuralın tamamı
Bir bağlamada hedef.ozellik = f(kaynak.ozellik) iki ayrı yetenek gerekir ve
bunları karıştırmamak önemlidir:
- Hedefin yalnız yazılabilir olması gerekir — okunabilen 11 bileşen
türünün hepsi yazılabilir. Yani
ilerleme_cubugu,etiket,dugmegibi türler pekâlâ bağlama HEDEFİ olabilir. - Kaynağın haber verebilmesi gerekir. İki yol vardır ve ikisi birlikte tüm türleri kapsar:
| Kaynak nasıl değişir | Haber yolu | Türler |
|---|---|---|
| Kullanıcı değiştirir | olay (degistiginde / secildiginde) |
girdi · metin_alani · kaydirici · onay_kutusu · acilir_liste · liste · tablo |
| Yalnız program değiştirir | programın her yazması | etiket · dugme · ilerleme_cubugu · grafik (+ yukarıdakiler programla yazıldığında) |
Kullanıcı bir etiketi klavyeyle değiştiremez; değeri ancak programın
yaptığı bir yazmayla değişir (E.metin = …, L.ekle(…), Tb.satir_ekle(…),
grafiğe veri eklemek) ve her yazma bağlamalara haber verir. Bu yüzden
girdi → etiket → etiket zinciri de canlıdır.
Bilinen tek boşluk: mantık (dogru/yanlis) özellikleri bağlanamaz —
secili = OtekiKutu.secili yazımı yanlis yazar ve güncellenmez. Derleyici
bunu uyarı olarak söyler, sessiz kalmaz; bugünkü karşılığı kaynağın
degistiginde: işleyicisinde atama yapmaktır.
Bağlama döngüleri — neden çökmüyoruz
a: b + "!" ve b: a + "?" gibi ıraksayan bir bağlama döngüsünün durağan
bir çözümü yoktur. KabaLang böyle bir döngüyü iki katmanda yakalar ve program
çökmez:
- Derleme anı — döngü bulunur ve uyarı basılır:
⚠ satır 11: bağlama döngüsü: L.metin → L.metin
▸ bu halkadaki bir özellik çalışma anında KESİLECEK ve güncellenmeyecek.
▸ döngüyü kırın: yönlerden birini `degistiginde:` olay işleyicisine taşıyın.
Derleme başarısız olmaz: döngü uyarıyla geçer ve program çalışır.
- Çalışma anı — yalnız program koşarken oluşan halkalar için ikinci bir koruma vardır. Kesilen bağlama bir kez bildirilir ve kalıcı olarak durdurulur:
kaba: bağlama döngüsü kesildi — "L.metin" kendi değerine dolaylı olarak bağlı.
▸ bu özellik artık güncellenmeyecek; döngüyü kaynakta kırın.
İki koruma birbirinin yedeği değildir: derleme anı denetimi dolaylı halkaları yakalar, çalışma anı koruması ise ancak program koşarken ortaya çıkan halkaları.
degistiginde: yolu da hâlâ geçerli
Bağlama, olay işleyicisini geçersiz kılmaz. Bir özelliği koşullu ya da yan etkili güncellemek istiyorsanız işleyici yazmaya devam edin:
kullan kaba.arayuz
pencere CanliOrnek:
baslik = "Canlı bağlama"
genislik = 420
yukseklik = 200
girdi AdGirdisi:
metin = "dünya"
ipucu = "Adınızı yazın..."
degistiginde:
SelamEtiketi.metin = "Merhaba " + AdGirdisi.metin
etiket SelamEtiketi:
metin = "Merhaba dünya"
stil = "font-size: 18px; font-weight: bold;"⚠️ Aynı özelliğe hem bildirimsel değer hem işleyici yazarsanız BAĞLAMA KAZANIR. İşleyici yine çalışır, ama bağlama değeri en son yazar ve ekranda onun sonucu kalır:
girdi G:
metin = "dünya"
degistiginde:
E.metin = "OLAY:" + G.metin # ← koşar, ama üzerine yazılır
etiket E:
metin = "BAGLAMA:" + G.metin # ← kazananÖlçüm: G.metin = "AYSE" sonrası E.metin = BAGLAMA:AYSE. İşleyici sessizce
yutulmaz — koşar, sonucu ezilir. Bir özelliği işleyiciyle yönetmek istiyorsanız
o özelliğe bildirimsel bir değer vermeyin (ya da sabit bir değer verin).
yineleyici — veriye göre bileşen üretme
Aynı bileşeni elle N kez yazmak yerine bir kez yazıp modele göre
çoğaltırsınız. QML'deki Repeaterın karşılığıdır.
kullan kaba.arayuz
pencere Liste:
baslik = "Yineleyici"
genislik = 320
yukseklik = 240
dikey_kutu:
yineleyici ["Ali", "Veli", "Ayşe"]:
etiket:
metin = oge
yineleyici 3:
etiket:
metin = "satır " + metin(sira)Gövdede iki ad tanımlıdır:
| Ad | Ne |
|---|---|
oge |
o anki öğe. Model bir sayı ise öğe sıranın kendisidir (QML'de modelData da öyledir) |
sira |
0 tabanlı sıra numarası |
İkisi de rezerve değildir: sira = 3 yazan kodunuz derlenmeye devam
eder, oge/sira yalnız bir yineleyici gövdesinde bu anlama gelir
(belgeler/14-anahtar-sozcukler.md).
Model yazımı
| Yazım | Çalışır mı |
|---|---|
yineleyici 7: |
✔ sabit tekrar |
yineleyici ["a", "b"]: |
✔ tek satırlık dizi sabiti |
yineleyici [ … ]: (çok satır) |
✔ satır ]: ile kapanır |
yineleyici liste: · yineleyici kopru.kisiler: |
✘ UYGULANMADI — aşağı bakın |
Gövdedeki bileşenler adsızdır
etiket: ← doğru
etiket Satir: ← HATAGövde her öğe için yeniden üretildiği için bir ad N bileşene verilmiş olurdu; bu yüzden gövdede ad yazmak açık bir derleme hatasıdır.
Kimlikler kendiliğinden üretilir: adsiz_etiket_1, adsiz_etiket_2, …
(adsiz_ öneki bildirimlerde rezervedir). Tek bir adlı bileşen
istiyorsanız onu gövdenin dışına yazın.
UYGULANMADI: canlı model
yineleyici <değişken>: ya da yineleyici <nesne>.<alan>: bugün
çalışmıyor ve sessizce düşmüyor — konumu ve bugünkü alternatifini
söyleyen bir hata alırsınız.
Bildirimsel bağlama yineleyici ile sorunsuz birleşir: çoğaltılan her
bileşen kendi canlı bağlamasını alır.
girdi G:
metin = "dunya"
dikey_kutu:
yineleyici ["A", "B"]:
etiket:
metin = oge + ":" + G.metinG.metin çalışma anında "AYSE" olduğunda iki etiket de güncellenir
(E1=A:AYSE · E2=B:AYSE).
Eksik olan başka bir şey: bağlama bir özelliğin değerini canlı yapar, canlı model ise bileşenlerin kendisini çalışma anında modele göre yaratıp silmeyi ister. Arayüz kitaplığında bileşen silme ve bağlamaları geri alma bugün yoktur; ikisi birlikte ele alınacak.
Sabit model (sayı ya da tek/çok satırlı dizi sabiti) bugün çalışır; veriye göre liste dolduran arayüzlerin bir kısmı böylece hemen yazılabiliyor, kalanı ise sessizce yanlış çalışmak yerine açıkça "henüz yok" diyor.
Bugünkü alternatif (çalıştığı ölçülmüş): öğe sayısı çalışma anında
değişiyorsa bileşen üretmeyin — içeriği değişen bir bileşen kullanın:
liste ya da tablo. L.ekle(...), L.sil(0), Tb.satir_ekle([...]) ve
Tb.satir_sil(0) gerçekten çalışır, yani modeliniz değiştiğinde yüzeyi
yeniden doldurabilirsiniz. Öğe sayısı sabit, yalnız değerleri
değişiyorsa yineleyici + bildirimsel bağlama bunu bugün zaten yapıyor
(yukarıdaki ölçüm). Kısaca: yineleyici bileşen üretir (sayı derleme
anında bellidir); liste/tablo içeriğini çalışma anında değiştirir.
Masaüstüne kurmak
kabalang masaustu ana.kbl # KDE menü kısayolu (.desktop)
kabalang demet ana.kbl --kur # .kapp uygulama demeti üretir ve kurar