PyQt與Qt具備極其類似的類族和API,並且再也不使用qmake系統和Q_OBJECT宏使得PyQt在沒有編譯連接時頻繁的錯誤並且代碼更加友好。html
from PyQt4 import QtCore, QtGui import sys if __name__ == '__main__': app = QtGui.QApplication(sys.argv); mainWindow = QtGui.QMainWindow(); mainWindow.setWindowTitle('Hello World from PyQt') mainWindow.show() label = QtGui.QLabel('Hello World', mainWindow) label.show() sys.exit(app.exec_())
將項目中全部文件均放入工做目錄下,使用python
或pythonw
命令執行入口文件,便可啓動PyQt應用。python
PyQt的可視化組件依舊以QtGui.QWidget做爲基類,與Qt的API很是相似。更多信息參見數據庫
PyQt doc服務器
Qt doc網絡
佈局使用示例:app
from PyQt4 import QtCore, QtGui import sys if __name__ == '__main__': app = QtGui.QApplication(sys.argv); # init Gui mainWindow = QtGui.QMainWindow(); mainWindow.setWindowTitle('Hello World from PyQt') button = QtGui.QPushButton('quit',mainWindow) # set layout mainLayout = QtGui.QVBoxLayout(mainWindow) mainLayout.addWidget(button) mainWindow.setLayout(mainLayout) # show GUI mainWindow.show() button.show() # init Signal-Slot , Run App QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), app, QtCore.SLOT('quit()')) # QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), app.quit) sys.exit(app.exec_())
Qt Designer 依舊生成.ui後綴名的xml文件保存界面設計,pyuic4工具能夠將.ui格式編譯爲.py格式的Python類。函數
確保pyuic4命令所目錄在path中,執行:pyuic4 firstDesign.ui > ui_firstDesign.py
,工具
能夠獲得文件 ui_firstDesign.py:oop
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'firstDesign.ui' # # Created by: PyQt4 UI code generator 4.11.4 # # WARNING! All changes made in this file will be lost! from PyQt4 import QtCore, QtGui try: _fromUtf8 = QtCore.QString.fromUtf8 except AttributeError: def _fromUtf8(s): return s try: _encoding = QtGui.QApplication.UnicodeUTF8 def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig, _encoding) except AttributeError: def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig) class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) MainWindow.resize(800, 600) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) # ... # something has been deleted self.statusbar = QtGui.QStatusBar(MainWindow) self.statusbar.setObjectName(_fromUtf8("statusbar")) MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) self.pushButton.setText(_translate("MainWindow", "OK", None))
導入ui_firstDesign
模塊,調用Ui_MainWindow.setupUi()
方法創建UI:佈局
#main.pyw import sys from PyQt4 import QtCore, QtGui from ui_firstDesign import Ui_MainWindow class MyForm(QtGui.QMainWindow): def __init__(self, parent = None): QtGui.QMainWindow.__init__(self,parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) if __name__ == '__main__': app = QtGui.QApplication(sys.argv) form = MyForm() form.show() sys.exit(app.exec_())
運行:
PyQt包含如下模塊:
核心非GUI組件,包括QObject,事件與信號槽,數據流等。
可視化組件與繪圖系統。
OpenGL 支持並與QtGui 結合
提供對可縮放矢量圖(SVG)的支持。
提供IP,TCP,UDP協議套接字支持,能夠開發簡單客戶端與服務器。
提供DOM與SAX兩種xml解析
提供對Sql的支持
與C++不一樣,Python標準庫具備不少方便使用的功能。在使用C++/Qt時做筆者選擇使用QString取代std::string,並使用Qt庫提供的網絡操做,多任務模型,數據庫模塊等。
在使用PyQt時可使用標準的Python 網絡,多任務和數據庫模塊。PyQt的QThread具備支持Qt的事件循環,在須要事件驅動機制可使用,但沒法避開GIL形成性能損失。
PyQt中絕大多數類均繼承了QObject類,QtCore.QObject與QtCore提供了一系列方法進行信號槽操做:
用於定義信號對象:signalObj = QtCore.pyqtSignal(*args)
使用裝飾器將一個函數對象裝飾爲槽函數:
from PyQt4 import QtGui, QtCore class MainWidget(QtGui.QWidget): def __init__(): pass @QtCore.pyqtSlot() def onClicked(self): QtGui.QMessageBox.information(self, u"Message", u"Get a Signal")
將表明函數簽名的字符串轉化爲信號槽,與Qt中的SIGNAL()和SLOT宏功能相同。
connect具備兩種經常使用方式,即槽可使用Python函數對象或者@QtCore.pyqtSlot()修飾的PyQt槽。
QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), app, QtCore.SLOT('quit()'))
或者:
QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), app.quit)
QObject.emit()用於發送信號,與Qt中的emit關鍵字功能相同。
class MyWidget(QtGui.QWidget): def emitSignal(self): self.emit(QtCore.SIGNAL('onClicked()'))
或者
class MyWidget(QtGui.QWidget): def emitSignal(self): self.mySignal = QtCore.pyqtSignal();
emit的可選參數能夠發送帶參數的信號:
self.emit(QtCore.SIGNAL('myClicked(QString)'), 'hello')
示例:
from PyQt4 import QtCore, QtGui import sys class MyButton(QtGui.QPushButton): def __init__(self, *args, **kwargs): QtGui.QPushButton.__init__(self, *args, **kwargs) self.connect(self, QtCore.SIGNAL("clicked()"), self.emitSignal) def emitSignal(self): self.emit(QtCore.SIGNAL('myClicked(QString)'), 'hello') app = QtGui.QApplication(sys.argv); mainWindow = QtGui.QMainWindow(); @QtCore.pyqtSlot() def showMsg(sig): QtGui.QMessageBox.information(mainWindow, "Msg", "Siganl Received:" + sig) if __name__ == '__main__': #my Signal button = MyButton('emit signal',mainWindow) mainWindow.connect(button,QtCore.SIGNAL('myClicked(QString)'), showMsg) #quit button quitButton = QtGui.QPushButton('quit', mainWindow) quitButton.move(0,40) QtCore.QObject.connect(quitButton, QtCore.SIGNAL('clicked()'), app, QtCore.SLOT('quit()')) # Start App mainWindow.show() button.show() sys.exit(app.exec_())
QObject.event()是PyQt中處理處理事件的另外一個機制, 繼承QObject()的類均可以重寫event系列方
系列實現事件處理。
event()方法進行事件分發通常不直接處理事件,類族中event()鏈式調用能夠方便的自定義事件處理。
一個事件將從最末端派生類的event函數開始處理,當一個事件被處理後調用QObject.accept()方法通知Qt結束該事件處理過程;;若該事件未被處理,Qt將會把該事件交由其父類的event函數處理。
bool QOject::isAccepted()
函數將返回表明事件是否被處理的邏輯值。
若在事件處理過程當中,調用了QObject::ignore()
方法,Qt將會終止事件向上遞歸,即忽略事件直接終止事件處理過程.忽略事件是危險的,儘可能不要這麼作。
示例,自定義事件處理:
from PyQt4 import QtCore, QtGui import sys class MyWidget(): def event(self,event): if(event.type() == QtCore.QEvent.KeyPress): if (event.key() == QtCore.Qt.Key_Escape): self.emit(QtCore.SIGNAL("escapePressed()")) event.accept() return True return super(MyWidget, self).event(event)
重寫鍵盤事件處理keyReleaseEvent()與繪圖paintEvent()等方法能夠方便的處理按鍵或者繪製界面。以及內置的計時系統timerEvent()。
注意必須設置位置參數event:def keyPressEvent(self, event):
示例,[ESC]鍵退出應用:
# !/usr/bin/python import sys from PyQt4 import QtGui, QtCore class Escape(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.setWindowTitle('escape') self.resize(250, 150) self.connect(self, QtCore.SIGNAL('closeEmitApp()'), QtCore.SLOT('close()')) def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: self.close() if __name__ == '__main__': app = QtGui.QApplication(sys.argv) qb = Escape() qb.show() sys.exit(app.exec_())
由於不須要Q_PROPERTY因此使用更加方便。
QAnimation示例:
from PyQt4 import QtCore, QtGui import sys if __name__ == '__main__': app = QtGui.QApplication(sys.argv) mainWindow = QtGui.QMainWindow() mainWindow.resize(400, 400) mainWindow.show() label = QtGui.QLabel('Animated Button', mainWindow) label.show() # Animation animation = QtCore.QPropertyAnimation(label, 'geometry', mainWindow) animation.setDuration(10 * 1000) animation.setKeyValueAt(0.5, QtCore.QRect(125, 250, 100, 30)) animation.setEndValue(QtCore.QRect(250, 0, 100, 30)) animation.start() #Run event loop sys.exit(app.exec_())
Graphics View示例:
from PyQt4 import QtCore, QtGui import sys if __name__ == '__main__': app = QtGui.QApplication(sys.argv) mainWindow = QtGui.QMainWindow() mainWindow.resize(300, 200) mainWindow.show() # Graphics View scene = QtGui.QGraphicsScene(mainWindow) scene.addText('Graphics View Rotate') view =QtGui.QGraphicsView(scene,mainWindow) view.resize(200,150) view.rotate(+45) view.show() #Run event loop sys.exit(app.exec_())