zoukankan      html  css  js  c++  java
  • 从Qt到PyQt

    Hello World

    PyQt与Qt具有极其相似的类族和API,而且不再使用qmake系统和Q_OBJECT宏使得PyQt在没有编译链接时频繁的错误而且代码更加友好。

    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_())
    

    将项目中所有文件均放入工作目录下,使用pythonpythonw命令执行入口文件,即可启动PyQt应用。

    可视化组件

    PyQt的可视化组件依旧以QtGui.QWidget作为基类,与Qt的API非常类似。更多信息参见

    PyQt doc

    Qt doc

    布局使用示例:

    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

    Qt Designer 依旧生成.ui后缀名的xml文件保存界面设计,pyuic4工具可以将.ui格式编译为.py格式的Python类。

    确保pyuic4命令所目录在path中,执行:pyuic4 firstDesign.ui > ui_firstDesign.py,

    可以得到文件 ui_firstDesign.py:

    # -*- 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_())
    

    运行:

    使用Python标准库

    PyQt包含以下模块:

    • QtCore

    核心非GUI组件,包括QObject,事件与信号槽,数据流等。

    • QtGui

    可视化组件与绘图系统。

    • QtOpenGL

    OpenGL 支持并与QtGui 结合

    • QtSvg

    提供对可缩放矢量图(SVG)的支持。

    • QtNetwork

    提供IP,TCP,UDP协议套接字支持,可以开发简单客户端与服务器。

    • QtXml

    提供DOM与SAX两种xml解析

    • QtSql

    提供对Sql的支持

    与C++不同,Python标准库具有很多方便使用的功能。在使用C++/Qt时作笔者选择使用QString取代std::string,并使用Qt库提供的网络操作,多任务模型,数据库模块等。

    在使用PyQt时可以使用标准的Python 网络,多任务和数据库模块。PyQt的QThread具有支持Qt的事件循环,在需要事件驱动机制可以使用,但无法避开GIL造成性能损失。

    信号槽与事件

    信号槽

    PyQt中绝大多数类均继承了QObject类,QtCore.QObject与QtCore提供了一系列方法进行信号槽操作:

    • QtCore.pyqtSignal()

    用于定义信号对象:signalObj = QtCore.pyqtSignal(*args)

    • @QtCore.pyqtSlot()

    使用装饰器将一个函数对象装饰为槽函数:

    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")
    
    • QtCore.SIGNAL() 与 QtCore.SLOT()

    将代表函数签名的字符串转化为信号槽,与Qt中的SIGNAL()和SLOT宏功能相同。

    • QObject.connect()

    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()

    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_())
    

    event()事件处理机制

    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_())
  • 相关阅读:
    【转】Android Lint分类及常见错误
    备忘
    【转】QRCode二维码生成方案及其在带LOGO型二维码中的应用
    如何控制横向和纵向滚动条的显隐?
    网页屏保
    过度方式
    让背景图不滚动
    自定义指定区域的文字大小
    定义本网页关键字
    通过层来实现渐淡淡出
  • 原文地址:https://www.cnblogs.com/Finley/p/5268861.html
Copyright © 2011-2022 走看看