2019独角兽企业重金招聘Python工程师标准>>>
使用pyqt需要先安装QT4。目前QT4最高支持到python3.4。QT5存在太多兼容性BUG,我们就不使用了。当然QT5下设计好的ui界面qt4下一样能用。
目录:
1、安装
2、设计窗口
3、添加控件
4、ui转py
5、py中显示窗口
6、按钮响应
7、耗时任务与多线程与信号
1、安装。
本文使用python3.4+qt4使用。其他版本请下载对应版本安装。方法一样!
下载链接&附python:https://pan.baidu.com/s/101lI6aDVegVqiZNphJY-EQ 密码:hu72
注意:python安装包建议还是跟电脑位数一样,一般建议都是x64位的。qt版本则必须与python版本对应,例如python27x64位的,那么安装的qt4必须是带 python27x64位的。如果这里没有适合你使用的qt4版本,可以百度下例如"pyqt4 2.7 x64"这样搜索。
QT4安装到python3.4的安装目录下,我就不多说了。
2、设计窗口
可以在 开始->所有程序->pyQt4 GPL v4....->Designer 打开qt设计师。
widget、mainwindow和dialog有什么区别,可以参考文献。https://www.cnblogs.com/584709796-qq-com/p/4949410.html
我简单说明一下:
mainwindow 是主窗口,有默认的菜单栏等。
widget 是对话框,一般用于简单提示。例如,简单的yes/no选择。
Dialog 也是对话框,一般用于有提示的多内容窗口。例如,弹出来的要求注册、登录、sn码注册等。
mainwindow 必须使用QMainWindow()初始化才能显示。
widget和Dialog 可以用QWidget ()或QMainWindow()初始化就能显示。
我选用mainwindow初始化了一个窗口。
【ps我个人更习喜欢widget。因为什么都没有可以让我随心所欲的设计】
3、添加控件
qt设计师非常方便,只需要拖拽就能加入新控件。双击控件能直接修改显示文本。右下角objectName能修改控件名。
我删除了菜单栏(窗口最上面右键删除),删除了状态栏(窗口最下面右键删除),并添加了一个名叫runbutton的按钮,和名叫labelstatus的文本框。
保存为ui_mainwindow.ui文件。
#ui_mainwindow.ui(代码可在后续的git中找到)【这是设计师自动生成的,大家不用理解,也不要修改哦】
MainWindow
0
0
381
196
主窗口
40
90
75
23
运行
190
92
54
20
待命
4、ui转py
html代码我们python无法使用。于是需要转成.py的文件。
我们在这ui所在文件夹,在cmd中运行下面的命令即可。【可以保存为.bat文件方便直接双击使用】
pyuic4.bat ui_mainwindow.ui -o ui_mainwindow.py
pyuic4.bat 是pyqt自带工具
xxxx.ui是你的ui文件名
-o xxxx.py 是指定转成py的文件名
如果你跟我一样有多个python和多个qt,我建议使用绝对路径运行。结果虽然没差异,但我还是追求严谨。
C:\Python34\Lib\site-packages\PyQt4\pyuic4.bat ui_mainwindow.ui -o ui_mainwindow.py
5、py中显示窗口
新建一个main.py文件。PYTHON_BAN的作用是识别运行环境。我们py3,可以直接赋值PYTHON_BAN=3。为什么这么写,可以参考我的另一篇博客。https://my.oschina.net/jacky326/blog/1838149
#main5.py
#-*-coding:utf-8-*-
from BASECLASS import PYTHON_BAN
import sys
if PYTHON_BAN in (2,):
#在py2下,这是为了处理中文乱码问题。py3下官方修复就不要这样处理了。
reload(sys)
sys.setdefaultencoding('utf-8')
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
from ui_mainwindow import Ui_MainWindow
class Dialog(QObject,Ui_MainWindow):
def __init__(self):
Ui_MainWindow.__init__(self)
QObject.__init__(self)
#如果是widget类型
#self.widget=QWidget()
#如果是mainwindow类型
self.widget = QMainWindow()
self.setupUi(self.widget)
self.widget.show()
if __name__ == '__main__':
app=QApplication(sys.argv)
ui = Dialog()
sys.exit(app.exec_())
直接运行就能显示了。
6、按钮响应
我们为按钮添加响应。需要先在类中添加一个按钮响应的函数(名字可自定)。然后在__init__结尾绑定按钮点击时的响应格式是 self.xxxxx按钮.clicked.connect(self.xxxxxx函数)
例如self.runbutton.clicked.connect(self.runbutton_down)
我比较建议把这样绑定按钮的逻辑放在一个单独的函数里,在__init__后立刻调用,当然这仅仅是为了美观。
#main.py
#-*-coding:utf-8-*-
from BASECLASS import PYTHON_BAN
import sys
if PYTHON_BAN in (2,):
#在py2下,这是为了处理中文乱码问题。py3下官方修复就不要这样处理了。
reload(sys)
sys.setdefaultencoding('utf-8')
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
import time
from ui_mainwindow import Ui_MainWindow
class Dialog(QObject,Ui_MainWindow):
def __init__(self):
Ui_MainWindow.__init__(self)
QObject.__init__(self)
#如果是widget类型
#self.widget=QWidget()
#如果是mainwindow类型
self.widget = QMainWindow()
self.setupUi(self.widget)
self.widget.show()
self._band_()
def _band_(self):
self.runbutton.clicked.connect(self.runbutton_down)
def runbutton_down(self):
self.labelstatus.setText(u'运行中')
#time.sleep(5)
self.labelstatus.setText(u'完成')
if __name__ == '__main__':
app=QApplication(sys.argv)
ui = Dialog()
sys.exit(app.exec_())
简单任务瞬间完成!!!
7、耗时任务与多线程与信号
可是这样是有问题的哦!!!假如,我们点击按钮会执行一个复杂任务,完成后提示完成。解除注释time.sleep(5)试试。会发现运行时,窗口无法拖动等,进入“无响应”的状态!
立刻想到这是因为主线程卡主了,最佳方案就是经典的多线程!
#main7.py
#-*-coding:utf-8-*-
from BASECLASS import PYTHON_BAN
import sys
if PYTHON_BAN in (2,):
#在py2下,这是为了处理中文乱码问题。py3下官方修复就不要这样处理了。
reload(sys)
sys.setdefaultencoding('utf-8')
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
import time,threading
#from ui_widget import Ui_MainWindow
from ui_mainwindow import Ui_MainWindow
class Dialog(QObject,Ui_MainWindow):
def __init__(self):
Ui_MainWindow.__init__(self)
QObject.__init__(self)
#如果是widget类型
#self.widget=QWidget()
#如果是mainwindow类型
self.widget = QMainWindow()
self.setupUi(self.widget)
self.widget.show()
self._band_()
def _band_(self):
self.runbutton.clicked.connect(self.runbutton_down)
def runbutton_down(self):
t = threading.Thread(target=self.runbutton_down_runner)
t.start()
def runbutton_down_runner(self):
self.labelstatus.setText(u'运行中')
time.sleep(5)
self.labelstatus.setText(u'完成')
if __name__ == '__main__':
app=QApplication(sys.argv)
ui = Dialog()
sys.exit(app.exec_())
这样基本就可以了。【嗯?居然可以了?】
好吧。如果可以了就可喜可贺完成吧。
失败就继续看吧。
我还是提一下吧,我以前刚学习pyqt的时候,在子线程里改变主线程的控件是会报错的。对!会报错!报错的大意是“控件不能在其他线程改变”。原本写到这应该就出现异常了。也许我以前用的qt有bug或者其他的吧。可以用就最好了,不可用就继续下去。
(假如)报错“控件不能在其他线程改变”,那么我们就需要用到QT的信号。
信号的初始化时要做的有两点:①信号必须在__init__运行之前就声明。信号建议全大写,这是C++编程时的编写规范,我希望沿用。例如:SHOW_STATUS = pyqtSignal(str)。
信号传入参数可以是任意多的数据类型(也可以空白)。假如我需要传入两个int和一个字符串,可以是SHOW_STATUS = pyqtSignal(int,int,str)。
②信号需要在使用前绑定调用函数,这可以是多个函数,并且不会相互覆盖,而是同时执行。【但我还是不建议这样使用,我建议一个信号绑定一个函数,以免混乱】这意味着,信号不能在运行中解绑。self.SHOW_STATUS.connect(self.show_status)绑定。
调用时使用self.SHOW_STATUS.emit(u'完成')即可发送信号。【发送信号】
#main7.py
#-*-coding:utf-8-*-
from BASECLASS import PYTHON_BAN
import sys
if PYTHON_BAN in (2,):
#在py2下,这是为了处理中文乱码问题。py3下官方修复就不要这样处理了。
reload(sys)
sys.setdefaultencoding('utf-8')
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
import time,threading
from ui_widget import Ui_MainWindow
#from ui_mainwindow import Ui_MainWindow
class Dialog(QObject,Ui_MainWindow):
SHOW_STATUS = pyqtSignal(str)
def __init__(self):
Ui_MainWindow.__init__(self)
QObject.__init__(self)
#如果是widget类型
#self.widget=QWidget()
#如果是mainwindow类型
self.widget = QMainWindow()
self.setupUi(self.widget)
self.widget.show()
self._band_()
def _band_(self):
self.runbutton.clicked.connect(self.runbutton_down)
self.SHOW_STATUS.connect(self.show_status)
self.SHOW_STATUS.connect(self.x)
def runbutton_down(self):
t = threading.Thread(target=self.runbutton_down_runner)
t.start()
def runbutton_down_runner(self):
#self.labelstatus.setText(u'运行中')
self.SHOW_STATUS.emit(u'运行中')
time.sleep(5)
#self.labelstatus.setText(u'完成')
self.SHOW_STATUS.emit(u'完成')
def x(self):
print('order!')
def show_status(self,message):
self.labelstatus.setText(message)
if __name__ == '__main__':
app=QApplication(sys.argv)
ui = Dialog()
sys.exit(app.exec_())
EX:
最后附上main.py真正完整正确的代码。
#main7.py
#-*-coding:utf-8-*-
from BASECLASS import PYTHON_BAN
import sys
if PYTHON_BAN in (2,):
#在py2下,这是为了处理中文乱码问题。py3下官方修复就不要这样处理了。
reload(sys)
sys.setdefaultencoding('utf-8')
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
import time,threading
#from ui_widget import Ui_MainWindow
from ui_mainwindow import Ui_MainWindow
class Dialog(QObject,Ui_MainWindow):
SHOW_STATUS = pyqtSignal(str)
def __init__(self):
Ui_MainWindow.__init__(self)
QObject.__init__(self)
#如果是widget类型
#self.widget=QWidget()
#如果是mainwindow类型
#self.widget = QMainWindow()
self.setupUi(self.widget)
self.widget.show()
self._band_()
def _band_(self):
self.runbutton.clicked.connect(self.runbutton_down)
self.SHOW_STATUS.connect(self.show_status)
def runbutton_down(self):
t = threading.Thread(target=self.runbutton_down_runner)
t.start()
def runbutton_down_runner(self):
self.SHOW_STATUS.emit(u'运行中')
time.sleep(5)
self.SHOW_STATUS.emit(u'完成')
def show_status(self,message):
self.labelstatus.setText(message)
if __name__ == '__main__':
app=QApplication(sys.argv)
ui = Dialog()
sys.exit(app.exec_())
代码:
git: https://gitee.com/kid0/pyqt_show.git
百度云:链接:https://pan.baidu.com/s/1CxYipjfeJCkyyuLbyK_WFg 密码:klfd
总结:
其实本来是要想说qt的信号重要性的,但似乎新版不会出现这问题。所以最后还是简要的说了下。以上是python+qt4的图形化界面显示的模板。