PyQt4 Türkçe Tutorial
Yazar: Oğuzhan Eroğlu ( oguzhan@oguzhaneroglu.com ) Son Güncelleme: 30-04-2008

Python un muhteşem dünyasına katılanlar onun ne kadar güzel bir dil olduğunu bilirler. Python hem kolaydır hem güçlüdür hemde kıvraktır. İşte böyle güzel bir dilin öntanımlı GUI(Grafik arayüz) kütüphanesi olan tkinter için ne yazıkki aynı şeyleri söyleyemeyiz. Tkinter her ne kadar kolay olsada güzel uygulamalar yazmak için yeterli değildir.

Bu yazımızda Qt4 GUI kütüphanesinin python için olan PyQt4 modülüne bir giriş yapacağız.
PyQt proje sayfası: http://www.riverbankcomputing.com

Bu dökümandaki örneklere; http://www.oguzhaneroglu.com/belgeler/pyqttut-tr/ornekler/ adresinden erişebilirsiniz.

Gerekenler:
Qt4
PyQt4
Qt4-Designer

Ayrıca bu yazıdan sonrada size çok yardımcı olacak qt-assistant'ıda kurmanızı öneririm.

Qt nin bazı modülleri:
QtGui -> Grafik arabirimi tasarlamak için gerekli olan modüldür.
QtCore -> Grafik arabirime bağlı olmayan temel bileşenleri içeren modül.
QtNetwork -> Ağ, internet işlemleri için gerekli olan modül.

Daha öncede dediğim gibi qt-assistant dan bütün Qt modülleri hakkında bilgi alabilirsiniz.

Yazı temel python bilginizin olduğunu varsayar.
Küçük bir örnek yapalım:

# -*- coding: utf-8 -*-

from PyQt4 import QtGui

import sys

app = QtGui.QApplication(sys.argv)
mainWindow = QtGui.QMainWindow()
mainWindow.setWindowTitle("Deneme")
mainWindow.show()
app.exec_()

#-*- coding: utf-8 -*- satırı ile uygulamamızı her karaktere uyumlu hale getiriyoruz.
from PyQt4 import QtGui satırı ile PyQt4 modülündeki GUI'yi tasarlayacağımız QtGui modülünü çağırıyoruz.
app = QtGui.QApplication(sys.argv) satırı ile Qt Uygulamamızı tanımladık ve sys.argv ile kullanıcıdan gelen argumanları verdik.(Bunun yerine QApplication([]) şeklinde boş bir listede verebilirdik.)
mainWindow = QtGui.QMainWindow() satırı ile penceremizi tanımladık.
mainWindow.setWindowTitle("Deneme") ile mainWindow değişkenmizin başlığını “Deneme” yaptık.
mainWindow.show() QMainWindow olarak tanımadlığımız değişkenimizi gösterme komutunu verdik.
app.exec_() satırı ile Qt uygulamamızı çalıştırdık.

Bundan sonraki tasarımlarımızı Qt4 Designer ile yapacağız.
Hemen KDE menüsünden
Geliştirme / Qt4 Designer yolunu izleyerek designerimizi açalım.
Bizi ilk olarak aşağıdaki gibi bir ekran karşılayacaktır.

buradan MainWindow u seçiyoruz. Şimdi ise aşağıdaki gibi bir ekran gelmiş olmalı:

Sol taraftan penceremize 1 adet
Push Button, 2 adet Line Edit, 1 adet de label yerleştirelim. ve penceremizin üst menüsüne Dosya, Yardım menülerini ekleyelim Dosya menüsüne Çık, Yardım menüsüne ise Hesap Makinesi Hakkında ve QT Hakkında öğelerini ekleyelim. Ayrıca Push Button ve label lerin üzerlerine çift tıklayarak isimlerini değiştirelim. ve başlığımızı değiştirmek için sağ taraftaki Property Editor deki windowTitle özelliğini “Hesap Makinesi” olarak değitşirelim.
Ayrıca widgetlerin adlarını Property Editör den
objectName özelliğinden değiştirebilirsiniz.
Şimdi görüntü aşağıdaki gibi olmuştur:

Artık GUI dosyamızı kaydedebiliriz. GUI'mizi
ui_makine.ui adıyla kaydettikten sonra konsolda dosyamızın bulunduğu dizinde pyuic4 ui_makine.ui -o ui_makine.py komutu ile ui dosyamızın python kodlarını oluşturuyoruz.
Buraya kadar herşey tamam şimdi kodlamaya geçebiliriz. Kodlamaya geçmeden önce şunu belirtelim pyuic4 ile oluşturduğumuz betiği 3 yaklaşımla kullanabiliriz: basit yaklaşım, tek miraslı yaklaşım, çok miraslı yaklaşım bu yazımızda çok miraslı yaklaşım kullanacağız.
Şimdi yine ui dosyamızın bulunduğu dizinde makine.py adlı bir dosya oluşturalım ve aşağıdaki kodları yazalım.

# -*- coding: utf-8 -*-

from PyQt4 import QtGui, QtCore
from ui_makine import Ui_MainWindow

class mainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)
    @QtCore.pyqtSignature("bool")
    def on_pushButton_clicked(self):
        self.toplam = int(self.lineEdit.text()) + int(self.lineEdit_2.text())
        self.label.setText(str(self.toplam))
    @QtCore.pyqtSignature("bool")
    def on_action_k_triggered(self):
        app.exit()
    @QtCore.pyqtSignature("bool")
    def on_actionQT_Hakk_nda_triggered(self):
        QtGui.QMessageBox.aboutQt(self)
    @QtCore.pyqtSignature("bool")
     def on_actionHesap_Makinesi_Hakk_nda_triggered(self):
         QtGui.QMessageBox.about(self, u"Hesap Makinesi Hakkında", u"Hesap yapar, çarpar, böler..")

app = QtGui.QApplication([])
mw = mainWindow()
mw.show()
app.exec_()

ve python makine.py komutu ile çalıştıralım.

İşte ilk işe yarar uygulamamızı yazdık! Şimdi biraz açıklayalım.
Qt de sinyaller ve slotlar vardır her widgetin sinyalleri vardır ve bu sinyallerin bir türü vardır. Sinyalleri bir slota bağlamanın değişik yolları vardır bunlardan birisi ilk makine örneğimizdeki gibidir. Bu yöntemde sınıfın içersinde hiçbir fonksiyon olmadan
@QtCore.pyqtSignature(“gonderilensinyalintürü”) kodu yazılır. ve hemen altına def on_widgetinadi_gonderdigisinyal(self): şeklinde slot tanımlanır. 2. yöntemi ise daha sonra anlatacağız.
Gördüğünüz gibi sınıfımızı tanımlarken GUI dosyamızdaki sınıfı miras aldık ayrıca QtGui deki QmainWindow'uda miras olarak aldık ve initimizde
QtGui.QMainWindow.__init__(self) ile QmainWindow initini çalıştırıyoruz. Aynı şekilde miras aldığımız sınıftaki setupUi fonksiyonunu çalıştırarak GUI'mizi ayarlıyoruz.
Qt deki nesnelerin onların gönderdiği sinyalleri, sinyallerin türlerini, metodlarını qt-assistant dan bakarak öğrenebilirsiniz.

Şimdi örneğimizi diğer bir yöntemle yazalım:

# -*- coding: utf-8 -*-

from PyQt4 import QtGui, QtCore
from ui_makine import Ui_MainWindow

class mainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)
        QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked(bool)"), self.topla)
        QtCore.QObject.connect(self.action_k, QtCore.SIGNAL("triggered(bool)"), self. cik)
        QtCore.QObject.connect(self.actionQT_Hakk_nda, QtCore.SIGNAL("triggered(bool)"), self.qthakkinda)
        QtCore.QObject.connect(self.actionHesap_Makinesi_Hakk_nda, QtCore.SIGNAL("triggered(bool)"), self.makinehakkinda)
    def topla(self):
        self.toplam = int(self.lineEdit.text()) + int(self.lineEdit_2.text())
        self.label.setText(str(self.toplam))
    def cik(self):
        app.exit()
    def qthakkinda(self):
        QtGui.QMessageBox.aboutQt(self)
    def makinehakkinda(self):
        QtGui.QMessageBox.about(self, u"Hesap Makinesi Hakkında", u"Hesap yapar, çarpar, böler..")


app = QtGui.QApplication([])
mw = mainWindow()
mw.show()
app.exec_()

Bu yöntemde ise; slotlar normal isimler ile yazılır ve sinyaller QtCore.QObject.connect(sinyalgonderenwidgetinadi, QtCore.SIGNAL("sinyaladi(sinyaltürü)"), sinyalinbağlandığıfonksiyon) kodu ile slotlara bağlanır.

Birde download uygulaması yazalım:
Qt Designeri açalım ve pencereye 2 adet label, 1 adet pushButton, 1 adet lineEdit 1 adet de progressBar yerleştirelim. ve progressBar widgetimizin value özelliğini property Editör den 0 yapalım. Ayrıca üst menüyüde aşağıdaki gibi düzenleyelim.


Şimdi sıra kodu yazmakta:

# -*- coding: utf-8 -*-

from PyQt4 import QtGui, QtCore, QtNetwork
from ui_downloader import Ui_MainWindow

class mainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)
        QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked(bool)"), self.indir)
    def setbar(self, deger, maximum):
        self.progressBar.setMaximum(maximum)
        self.progressBar.setValue(deger)
    def download_son(self):
        self.progressBar.setValue(0)
    def indir(self):
        self.file = QtCore.QFile("indirilen_dosya")
        self.download = QtNetwork.QHttp("www.riverbankcomputing.com")
        QtCore.QObject.connect(self.download, QtCore.SIGNAL("dataReadProgress(int,int)"), self.setbar)
        QtCore.QObject.connect(self.download, QtCore.SIGNAL("done(bool)"), self.download_son)
        self.download.get("/static/Downloads/PyQt4/PyQt-x11-gpl-4.3.3.tar.gz", self.file)
    @QtCore.pyqtSignature("bool")
    def on_action_k_triggered(self):
        app.exit()
    @QtCore.pyqtSignature("bool")
    def on_actionDownloader_Hakk_nda_triggered(self):
        QtGui.QMessageBox.about(self, u"Downloader Hakkında", u"Dosya indirir.")
    @QtCore.pyqtSignature("bool")
    def on_actionQT_Hakk_nda_triggered(self):
        QtGui.QMessageBox.aboutQt(self)

app = QtGui.QApplication([])
mw = mainWindow()
mw.show()
app.exec_()

Şimdi size biraz karışık gelebilir burda anlamanız açısından 2 çeşit sinyal/slot kullanımı yaptık. Açıklayacak olursak; En baştada belirttiğim gibi ağ, internet için QtNetwork modülünü kullanabiliriz. Bir diğer kafa karıştıran kısım ise QFile ve progressBar ın nasıl çalıştığı olmuş olabilir. QFile yi indirdiğimiz dosyayı yazmak için kullandık. self.download = QtNetwork.QHttp("www.riverbankcomputing.com") kodu ile siteye bağlandık ve daha sonra sinyallerimizi slotlara bağladık. self.download.get("/static/Downloads/PyQt4/PyQt-x11-gpl-4.3.3.tar.gz", self.file) kodu ile sitedeki bir dosyayı indiriyoruz ve self.file değişkeninde olan QFile dosyasına yazdırıyoruz, yani dosyamız bilgisayarımızda oluyor. Eğer QFile kullanmasaydık yani sadece self.download.get("/static/Downloads/PyQt4/PyQt-x11-gpl-4.3.3.tar.gz") kodunu kullansaydık self. download değişkeninde dosyanın içeriği olacaktı ve bunu python un normal open fonksiyonunu kullanarak yazdırabilirdik. Dosyayı okumak için self.download.readAll() fonksiyonunu kullanıyoruz bu fonksiyon bize dosyanın içeriğini str cinsinden veriyor.
progressBar ın çalışmasına gelecek olursak QHttp değişkenlerinin dataReadProgress diye bir sinyali vardır bu sinyal bize tamamlanan değer ve toplam değeri verir. QtCore.QObject.connect(self.download, QtCore.SIGNAL("dataReadProgress(int,int)"), self.setbar) burdaki intler değerlerdir ve QHttp nin dataReadProgress sinyalini setbar slotuna bağladık.
        self.progressBar.setMaximum(maximum)
        self.progressBar.setValue(deger)
Kodları ile değerlerini anlık olarak değiştirmesini sağladık.

Peki bundan sonra ne yapacaksınız ?
Bu yazıyı okuduktan sonra eminimki PyQt4 öğrenmeye başladınız ve hatta biraz öğrendiniz bile artık küçük örnekler yaparak, trolltech in dökümanlarından faydalanarak dahada çok öğrenebilirsiniz.