Atölye bölümümüzün açılmasıyla beraber yayınlamaya başlayacağımız PyQt dersleri yazı dizisinde, Qt görsel arayüz kitaplığının Python ile kullanılabilmesini sağlayan PyQt4 ile kolay ve hızlı bir şekilde görsel arayüze sahip yazılım geliştirmeyi öğreneceksiniz. Dersleri daha iyi anlayabilmek için, öncelikle İnternet’te kolayca bulabileceğiniz Python dili ve nesne yönelimli programlama hakkındaki kaynakları okumanız faydalı olacaktır.

Neden PyQt?

Çoğu programlama dilinde, aylar önce kendi ellerinizle yazdığınız bir koda tekrar baktığınızda kodun ne yaptığını anlamakta güçlük çekersiniz. Python’da ise bu durum farklıdır. Python’un sadeliği sayesinde kodun ne yaptığını anlamak epey kolaylaşır ve bu sayede büyük projelerde kodun yönetimi kolaylaşır. Qt arayüz kitaplığının tutarlılığı, zengin belgelendirmesi ve her platformda göze hoş görünen uygulamalar oluşturmayı sağlaması, projelerimde bu kitaplığı kullanmamdaki en büyük etken olmuştur. Qt, grafik arayüz kitaplıklarının yanında pek çok yardımcı kitaplık ve araç da içermektedir. Qt ile birlikte gelen modüllerin bazıları ve araçlar aşağıda verilmiştir:

  • QtCore -> Grafik arayüze ihtiyaç duymayan temel bileşenler
  • QtGui -> Grafik arayüz
  • QtNetwork -> Ağ ve İnternet
  • QtSql -> Veritabanlarıyla bilgi alışverişi
  • QtOpenGL -> OpenGL kullanarak grafik kartıyla hızlandırılan uygulamalar için
  • QtScript -> Uygulamanıza kolayca betik desteği kazandırır
  • QtSvg -> SVG dosyalarını görüntüler
  • QtXml -> XML dosyalarını işlemede kullanılır
  • Designer -> Grafik arayüz tasarımı
  • Assistant -> Qt Belgeleri arasında dolaşmak için
  • Linguist -> Çeviri işleri için

Buradaki modüllere ek olarak 2008 yazında çıkacak olan Qt’nin 4.4 sürümü Phonon ve Webkit modüllerine de sahip olacak. Phonon ile video dosyalarını görüntüleyip sesleri çalabilmeniz mümkün olduğu gibi, Webkit sayesinde standartlara en uyumlu web sayfası görüntüleme motoru da elinizin altında olacak. Bütün bu modüllerin platform bağımsız çalışacağını düşünürsek, Qt’nin bu alanda yeni bir çağ başlattığını görebiliriz.

Kurulum

Pardus kullanıyorsanız, Paket Yöneticisi’nden PyQt4 assistant-qt4 designer-qt4 ve linguist-qt4 paketlerini kurarak tam bir PyQt4 geliştirme ortamına sahip olabilirsiniz. Aynı paketler diğer dağıtımlarda da python-qt4 adıyla yer alıyor. Diğer işletim sistemleri içinse kurulum dosyalarını buradan indirebilirsiniz: http://www.riverbankcomputing.co.uk/pyqt/download.php

Şimdi PyQt4 ile gelen araçları kısaca inceleyelim:

Designer

Daha önce de belirtildiği gibi Designer, grafik arayüzleri tasarlamak için kullanılıyor. İlerleyen bölümlerde designer ile neler yapılabileceğini ayrıntılı olarak işleyeceğiz.

Assistant

Tüm Qt belgelendirmesine bu aracı kullanarak erişebilirsiniz. Assistant, ne kadar tecrübeli olursanız olun, geliştirme süreci boyunca sürekli olarak açık kalması gereken bir yardımcıdır. Normalde C++ geliştiricileri için hazırlanmış olan Assistant, programınızı Python ile yazsanız bile çok faydalıdır.

Linguist

Yüzünü pek sık görmeyeceğiniz bu araç, çok dil destekli olarak geliştirdiğiniz yazılımları İngilizce dışında dillere çeviren kişilere kolaylık sağlıyor.

İlk Uygulama: Merhaba Dünya

Bu bölümde, hiçbir işe yaramayan, sadece “Merhaba Dünya” başlıklı bir ana pencereden oluşan bir PyQt4 uygulamasını inceleyeceğiz.

Örneği çalıştırmak istiyorsanız sevdiğiniz bir metin düzenleyicisini kullanarak aşağıdaki kodları merhaba.py adlı bir dosyaya kaydedin:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui

def main():
    app = QtGui.QApplication(sys.argv)

    mainWindow = QtGui.QMainWindow()
    mainWindow.setWindowTitle(u"Merhaba Dünya")
    mainWindow.show()

    return app.exec_()

if __name__ == "__main__": main()

Bu arada, programınızı yazarken bazı geleneklere sadık kalmanızı öneririm. Bunlara uyduğunuz takdirde kodunuz her düzenleyicide aynı şekilde görünecektir, böylece farklı bir düzenleyici kullanmanız gerektiğinde güçlük çekmeyeceksiniz. Metin düzenleyicinizde; tab karakteri yerine boşluk kullanarak, sekme genişliğini 4 boşluğa çevirerek, Python girinti kipini kullanarak ya da bunlara benzer isimdeki ayarları yaparak programınızı Python geleneklerine daha uygun yazabilirsiniz.

Şimdi programdaki satırları tek tek inceleyelim:

#!/usr/bin/python

Bu satır Python betiğimizin kolayca çalıştırılabilmesine ve diğer programlar tarafından Python betiği olarak tanınmasına yarıyor.

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

Bu satırda ise programımızın pek çok dilin karakter setinin bir arada kullanılmasını destekleyen UTF-8 karakter kodlamasını kullanacağını belirtiyoruz.

import sys

Burada Python’un standart sys modülünü yüklüyoruz. Qt4 programımıza konsoldan verilen parametreleri gönderebilmek için bu modüldeki argv’yi kullanacağız.

from PyQt4 import QtGui

Grafik arayüzü olan bir program yapacağımız için QtGui modülünü yüklüyoruz.

def main():

Bu satır Python yorumlayıcısına ana fonksiyonumuzu tanımlayacağımızı belirtiyor.

app = QtGui.QApplication(sys.argv)

Arayüzü olan her Qt uygulamasının olmazsa olmaz bileşeni QApplication nesnesidir. Bu satırda app adında bir QApplication nesnesi oluşturuyoruz ve buna konsoldan gelen parametreleri veriyoruz. Kullanıcılar, konsoldan verilen parametrelerle uygulamanızın kullandığı tema gibi bazı özellikleri değiştirebilirler. QApplication ve diğer tüm Qt sınıfları ile ilgili ayrıntılı bilgiyi Assistant’tan alabilirsiniz.

mainWindow = QtGui.QMainWindow()

Ana penceremiz burada oluşturuluyor.

mainWindow.setWindowTitle(u"Merhaba Dünya")
mainWindow.show()

Burada ise ana penceremizin başlığı Merhaba Dünya yapılıyor ve ardından pencere gösteriliyor. Buradaki u”Merhaba Dünya”da olduğu gibi karakter dizilerinin başında u karakterini kullanarak İngilizce’de olmayan karakterlerin düzgün görünmesini sağlayabilirsiniz.

return app.exec_()

Grafik arayüzlü programlar, arayüzlerini sunabilmek için sürekli çalışır durumda olup işlemciyi meşgul ederler. Bu satır, programımızın çalışır durumda kalmasını sağlayan döngüyü başlatıyor.

if __name__ == "__main__":
    main()

Bu satırlar ise Python betiği çalıştırılmak istendiğinde main() fonksiyonunun çalışmasını sağlıyor.

Şimdi gelelim çalıştırmaya… PyQt programımızı çalıştırmak için çeşitli yöntemler mevcuttur:

  • Konsolda python merhaba.py komutunu kullanabilirsiniz.
  • merhaba.py’yi sağ tıklayınca gelen menüde Birlikte aç > Diğer‘i seçip çalıştırılacak programın adı yerine pythonyazabilirsiniz.
  • Kullandığınız masaüstünün özelliklerini kullanarak bir başlatıcı oluşturabilir ve komut olarak python merhaba.pyverebilirsiniz. Böylece sadece bu başlatıcıyı tıklayarak programınızı çalıştırabilirsiniz.

Daha karmaşık bir örnek

Bu örneğimizde, metin dosyalarını açıp düzenleyerek kaydetmeye yarayan bir metin düzenleyicisi yapacağız.

Arayüzün hazırlanması

Designer’da Dosya menüsünden Yeni’yi tıklayarak bir Main Window oluşturalım. Ana penceremize Dosya, Yardım menülerini ve QTextEdit parçacığını ekleyelim. Dosya menüsünün altına Yeni, Aç, Kaydet, Çıkış; Yardım menüsünün altına da Düzenleyici Hakkında ve Qt Hakkında eylemlerini ekleyelim. Eklediğimiz QTextEdit parçacığının ekran görüntüsündeki gibi tüm pencereyi kaplaması için, parçacığı seçtikten sonra Form menüsünden Izgara içerisine yerleştir‘i seçelim. Son olarak da ana penceremizi seçip Özellik düzenleyicisinden windowTitle‘ı Düzenleyici olarak değiştirelim ve dosyayı mainwindow.ui adıyla kaydedelim.

Kodların yazılması

Öncelikle ana penceremizi hayata geçirecek kodları, daha sonra ise programı oluşturacak kodları yazalım. Qt Designer ile hazırladığımız ui dosyasını PyQt uygulamasında kullanabilmek için çeşitli yöntemler mevcuttur:

  • PyQt4’ün uic modülü kullanılarak .ui dosyası program açıldıktan sonra yorumlanabilir. Bu yöntem kısmen yavaş olmakla beraber sağladığı tek kolaylık projedeki dosya sayısını azaltmaktır.
  • PyQt4 ile birlikte gelen pyuic4 aracını kullanarak pyuic4 mainwindow.ui -o ui_mainwindow.py komutuyla .ui dosyasını ui_mainwindow.py adındaki bir Python betiğine dönüştürebilirsiniz. Dönüşüm işlemi, program çalışması sırasında gerçekleşmediği için bu yöntem çok daha hızlıdır. Bu yöntemde oluşturduğunuz python betiğini üç farklı yaklaşımla programınızda kullanabilirsiniz: basit yaklaşım, tek miraslı yaklaşım, çok miraslı yaklaşım. Yaklaşımlar hakkındaki ayrıntılı bilgiyi Assistant’ta Home > Qt Designer Manual > Using Forms and Components bölümünden edinebilirsiniz.

Bu örneğimizde, kodu göze en hoş görünen ve düzenleme yapması en kolay yaklaşım olan, çok miraslı yaklaşımı kullanacağız. Çok miraslı yaklaşımda, oluşturduğumuz bir sınıfta hem pyuic4’ün ui dosyamızdan oluşturduğu sınıfı, hem de Qt’nin bir sınıfını miras alan yeni bir sınıf oluştururuz. Sonuç olarak mainwindow.py dosyamızın ilk hali şöyle olacaktır:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from PyQt4 import QtGui
from ui_mainwindow import Ui_MainWindow

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)

Kodları satır satır inceleyelim:

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):

Bu satırda MainWindow adında bir sınıf oluşturuyor ve bu sınıfı oluştururken Qt’nin QMainWindow sınıfını ve ui dosyamızdan pyuic4 ile oluşturduğumuz Ui_MainWindow sınıfımızı miras alıyoruz.

def __init__(self):
    QtGui.QMainWindow.__init__(self)
    self.setupUi(self)

Bu satırlar MainWindow sınıfımızdan yeni bir nesne oluşturulduğunda çalışacaktır. Öncelikle QMainWindow’un kendi oluşturucusunu çağırıyor ve ardından Ui_MainWindow‘un içindeki setupUi‘yi çağırarak ana pencerenin istediğimiz hale gelmesini sağlıyoruz.

Bu kodları kullanan bir main.py dosyası ise tıpkı ilk örneğimizdeki gibi olacaktır:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui
from mainwindow import MainWindow

def main():
    app = QtGui.QApplication(sys.argv)

    mainWindow = MainWindow()
    mainWindow.show()

    return app.exec_()

if __name__ == "__main__":
    main()

Bu şekilde yazdığımız programı çalıştırmak için python main.py komutunu vermemiz yeterli olacaktır. Programı bu haliyle çalıştırdığınızda göreceğiniz gibi sadece Designer’da hazırladığımız pencereyi oluşturduk ve gösterdik. Pencereye işlev katmak için mainwindow.py dosyasını aşağıdaki gibi düzenlemeliyiz:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from PyQt4 import QtCore
from PyQt4 import QtGui
from ui_mainwindow import Ui_MainWindow

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)
        self.fileName = None

    @QtCore.pyqtSignature("bool")
    def on_actionYeni_triggered(self):
        self.fileName = unicode(QtGui.QFileDialog.getSaveFileName(self, u"Düzenlenecek dosyayı seçin", ".", u"Metin dosyaları (*.txt)"))
        file = open(self.fileName, 'w')
        file.write(self.textEdit.toPlainText())
        file.close()
        self.actionKaydet.setEnabled(True)
        self.textEdit.setEnabled(True)
        self.statusBar().showMessage(QtCore.QString(u"%1 dosyası oluşturuldu").arg(self.fileName))

    @QtCore.pyqtSignature("bool")
    def on_actionA_triggered(self):
        self.fileName = unicode(QtGui.QFileDialog.getOpenFileName(self, u"Düzenlenecek dosyayı seçin", ".", u"Metin dosyaları (*.txt)"))
        file = open(self.fileName, 'r')
        self.textEdit.setText(unicode(file.read()))
        file.close()
        self.actionKaydet.setEnabled(True)
        self.textEdit.setEnabled(True)
        self.statusBar().showMessage(QtCore.QString(u"%1 açıldı").arg(self.fileName))

    @QtCore.pyqtSignature("bool")
    def on_actionKaydet_triggered(self):
        if self.fileName is None:
            self.fileName = unicode(QtGui.QFileDialog.getSaveFileName(self, u"Düzenlenecek dosyayı seçin", ".", u"Metin dosyaları (*.txt)"))
            file = open(self.fileName, 'w')
            file.write(self.textEdit.toPlainText())
            file.close()
            self.statusBar().showMessage(QtCore.QString(u"%1 kaydedildi").arg(self.fileName))

    @QtCore.pyqtSignature("bool")
    def on_action_k_triggered(self):
        self.close()

    @QtCore.pyqtSignature("bool")
    def on_actionD_zenleyici_Hakk_nda_triggered(self):
        QtGui.QMessageBox.about(self, u"Düzenleyici Hakkında", u"Metin dosyalarınızı düzenler.")

    @QtCore.pyqtSignature("bool")
    def on_actionQt_Hakk_nda_triggered(self):
        QtGui.QMessageBox.aboutQt(self)

Bu şekilde yazdığımız zaman Qt’nin autoconnect özelliği sayesinde metodlarımız otomatik olarak sinyallere bağlanacak ve dolayısıyla menüden bir eylemi tıkladığımızda bu dosyadaki ilgili metodumuz çalışacaktır. Sinyal kavramından kısaca bahsetmek gerekirse; grafik arayüzü kullanırken yaptığımız her işlem (fareyi kımıldatmak, bir yere tıklamak, klavyedeki bir tuşa basmak) bir sinyal yayar ve eğer bu sinyali bir kod parçasına bağlamışsak, sinyal her yayıldığında bağladığımız kod parçası çalışır. PyQt’de her nesnenin kendine özgü sinyalleri bulunur. Bunların ne olduğunu ve sinyal kavramı hakkındaki detaylı açıklamayı yine Assistant’tan okuyabilirsiniz. Autoconnect’in düzgün çalışması için metodun başına, sinyalin gönderdiği parametrenin türünü @QtCore.pyqtSignature(“parametrenintürü”) şeklinde belirtmelisiniz. Bunun hemen altına def on_sinyalgönderennesne_sinyalinadı(self): yazarak sinyal geldiğinde ne yapılacağını belirtiriz. Eğer bağlayacağımız sinyal birden fazla parametre gönderiyorsa, bunları virgülle ayırarak belirtebiliriz.

Dikkat ederseniz bu örnekteki programımızda dosyayı açarken ve kaydederken bu işlemlerin başarılı olup olmadığını kontrol etmedik. Dosya işlemlerinde Qt’nin mis gibi QFile sınıfı dururken Python’un dosya fonksiyonlarını kullandık. Üstüne üstlük bir de arayüz metinlerini Türkçe yaparak programımızın diğer dillere çevrilmesini engelledik. Tabi ki burada böyle göstermemin nedeni örneğin küçük boyutlu kalabilmesiydi. Siz, gerçek hayatta kullanılacak programlarda bu hataları yapmamaya dikkat edin. Bunlara rağmen metin düzenleyicimiz, QTextEdit kullandığımız için geri alma, kopyalama ve yapıştırma gibi işlemlere doğuştan sahip olacaktır.

Bir sonraki konumuz programımıza dil desteğinin ve simgelerin nasıl ekleneceği olacak. Görüşmek üzere.

Önceki makaleOpenCity Oyunu
Sonraki makaleSavage: The Battle For Newerth Oyunu

BİR CEVAP BIRAK

Please enter your comment!
Please enter your name here