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 ->OpenGLkullanarak grafik kartıyla hızlandırılan uygulamalar için
- QtScript -> Uygulamanıza kolayca betik desteği kazandırır
- QtSvg ->SVGdosyaları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.pyadlı 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ünyayapılıyor ve ardından pencere gösteriliyor. Buradakiu”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ğindemain()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:
- Konsoldapython merhaba.pykomutunu kullanabilirsiniz.
- merhaba.py’yi sağ tıklayınca gelen menüdeBirlikte aç > Diğer‘i seçip çalıştırılacak programın adı yerinepythonyazabilirsiniz.
- Kullandığınız masaüstünün özelliklerini kullanarak bir başlatıcı oluşturabilir ve komut olarakpython 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 sonraFormmenüsündenIzgara içerisine yerleştir‘i seçelim. Son olarak da ana penceremizi seçip Özellik düzenleyicisindenwindowTitle‘ı Düzenleyici olarak değiştirelim ve dosyayımainwindow.uiadı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ı kullanarakpyuic4 mainwindow.ui -o ui_mainwindow.pykomutuyla .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’taHome > Qt Designer Manual > Using Forms and Componentsbö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ç olarakmainwindow.pydosyamı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ğumuzUi_MainWindowsınıfımızı miras alıyoruz.
def __init__(self): QtGui.QMainWindow.__init__(self) self.setupUi(self)
Bu satırlarMainWindowsınıfımızdan yeni bir nesne oluşturulduğunda çalışacaktır. Öncelikle QMainWindow’un kendi oluşturucusunu çağırıyor ve ardındanUi_MainWindow‘un içindekisetupUi‘yi çağırarak ana pencerenin istediğimiz hale gelmesini sağlıyoruz.
Bu kodları kullanan birmain.pydosyası 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çinpython main.pykomutunu 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çinmainwindow.pydosyası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’ninautoconnectö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ınadef 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.