Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Qt'de .ui Dosyasından Kalıtım Alınca Yaşadığım Interface Kabusu

devnix

Üye
Katılım
14 Mart 2026
Mesajlar
40
Geçenlerde yine bir Qt projesine daldım. Hızlı prototipleme için Qt Designer'da arayüzü çizip, .ui dosyasından pyuic5 ile o sihirli kodu generate etmek... İlk başta mükemmel görünüyordu. Kod temiz, arayüz ayrı, hayat güzel.

🪄 Sihirli Başlangıç

Şu klasik yöntem:
Python:
class AnaPencere(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

setupUi(self)[/CODE] çağrısıyla, tasarladığın tüm widget'lar (QPushButton, QLineEdit) sanki sihirle sınıfının özellikleri haline geliyor. self.pushButton deyip direkt erişebiliyorsun. İlk yaptığımda "Vay be, Qt ne kadar akıllı!" dedim. Gerçekten pratikti.

🧩 Dependency Injection Duvarı

Sonra proje büyüdü. Test yazmak, bağımlılıkları yönetmek (Dependency Injection) ve katmanları ayırmak gerekti. İşte o zaman işler çığırından çıktı.

Diyelim ki butona tıklayınca bir servisi (ApiService) çağıracak bir MainPresenter veya ViewModel yazmak istiyorsun. O sihirli kalıtım yüzünden, arayüz (Ui_MainWindow) ve mantık (AnaPencere) sıkı sıkıya birbirine bağlanmış oluyor. AnaPencere sınıfım, Ui_MainWindow'un generate edilmiş tüm widget'larını bilmek ZORUNDA. Test yazmak için bu widget'ları mock'lamak ya da farklı bir arayüz implementasyonu kullanmak neredeyse imkansız hale geliyor.

Kafayı yiyecektim. Şaka gibi ama, o pratik sihir, kodumu test edilemez, esnek olmayan bir yapıya dönüştürmüştü.

🔧 Çözüm Arayışı ve "Composition"

StackOverflow'da bile tam istediğim cevabı bulamadım. Meğerse sorun, inheritance (kalıtım) yerine composition (birleştirme) kullanmamakmış.

Sonunda bulduğum pattern şu:
1. .ui dosyasını ve ondan generate edilen kodu (ui_mainwindow.py) sadece bir "görünüm" (View) sınıfına enjekte ediyorsun.
2. Ana penceren, bu görünüm sınıfını bir özellik (self.view) olarak tutuyor.
3. Tüm iş mantığını (business logic) ayrı bir sınıfta (Presenter) yazıyorsun ve bu presenter'a görünümü enjekte ediyorsun.

Kaba bir örnek:
Python:
class MainView(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow() # Generate edilen sınıfı oluştur
        self.ui.setupUi(self) # Arayüzü bu pencereye kur

class MainPresenter:
    def __init__(self, view: MainView):
        self.view = view
        self._connect_signals()

    def _connect_signals(self):
        self.view.ui.pushButton.clicked.connect(self._on_button_clicked)

    def _on_button_clicked(self):
        # İş mantığı burada. View'a sadece self.view.ui üzerinden eriş.
        print("Butona tıklandı!")

Bu sayede, MainPresenter'ı test ederken, MainView yerine sahte (mock) bir görünüm objesi geçebiliyorsun. Arayüzü değiştirmek istediğinde sadece MainView sınıfını değiştirmen yetiyor.

💎 Sonuç ve İsyan

Evet, ilk baştaki sihirli yöntem hızlı prototip ve küçük araçlar için harika. Ama proje birazcık büyüyünce, o sihir seni esir alıyor. Composition over Inheritance ilkesi burada da kurtarıcı oldu.

Siz de Qt'de böyle bir saçmalık yaşadınız mı? `.ui` dosyalarıyla çalışırken daha temiz, test edilebilir bir yönteminiz var mı? Yoksa ben mi işi abartıyorum? Yorumlara yazın, tartışalım!
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri