美发网站 源代码,图片网站开发,上海网站建设定制,深圳企业信息查询系统PySide2/PySide6、PyQt5/PyQt6#xff1a;都是基于Qt 的Python库#xff0c;可以形象地这样说#xff0c;PySide2 是Qt的 亲儿子(Qt官方开发的) #xff0c; PyQt5 是Qt还没有亲儿子之前的收的 义子 #xff08;Riverbank Computing这个公司开发的#xff0c;有商业版权限…PySide2/PySide6、PyQt5/PyQt6都是基于Qt 的Python库可以形象地这样说PySide2 是Qt的 亲儿子(Qt官方开发的) PyQt5 是Qt还没有亲儿子之前的收的 义子 Riverbank Computing这个公司开发的有商业版权限制。
两个库的使用 对程序员来说差别很小它们的调用接口几乎一模一样。如果你的程序是PyQt5开发的通常只要略作修改比如把导入的名字从 PyQt5 换成 PySide2 就行了。反之亦然。 对应PySide2-PyQt5、PySide6-PyQt6
安装pyside2(推荐使用)
pip install pyside2 -i https://pypi.douban.com/simple/ 安装pyside6
pip install pyside6安装pyqt5
pip install pyqt5-tools安装pyqt6
pip install pyqt6-tools问题运行pyside2代码时发生初始化问题 解决 方法1 在代码头中加入环境变量
import sys, os
import PySide2
from PySide2.QtWidgets import *
dirname os.path.dirname(PySide2.__file__)
plugin_path os.path.join(dirname, plugins, platforms)
os.environ[QT_QPA_PLATFORM_PLUGIN_PATH] plugin_path
print(plugin_path)方法2 把 PySide2 或者 PyQt5 安装在解释器目录下的 \plugins\platforms 目录添加到环境变量Path中。
比如我的环境就是把这个路径加到 环境变量 Path 中
D:\Anaconda\envs\virtual_pytorch\Library\plugins\platforms1 基础—(控件、动作、封装)
1.1 控件 (QtWidgets)
QApplication 提供了整个图形界面程序的底层管理功能比如初始化、程序入口参数的处理用户事件对界面的点击、输入、拖拽分发给各个对应的控件等等。所以我们必须在任何界面控件对象创建前先创建它。
app QApplication([])QMainWindow、QPlainTextEdit、QPushButton 是3个控件类分别对应界面的主窗口、文本框、按钮。他们都是控件基类对象QWidget的子类。要在界面上 创建一个控件 就需要在程序代码中 创建 这个 控件对应类 的一个 实例对象。
window QMainWindow()
window.resize(500, 400)
window.move(300, 310)
window.setWindowTitle(窗口名)textEdit QPlainTextEdit(window)
textEdit.setPlaceholderText(文本框名)
textEdit.move(10,25)
textEdit.resize(300,350)button QPushButton(按钮名, window)
button.move(380,80)window.show() # 显示窗口app.exec_() # 进入QApplication的事件处理循环接收用户的输入事件在 Qt 系统中控件widget是 层层嵌套 的除了最顶层的控件其他的控件都有父控件。QPlainTextEdit、QPushButton 实例化时都有一个参数window就是指定它的父控件对象 是 window 对应的QMainWindow 主窗口。而 实例化 QMainWindow 主窗口时却没有指定 父控件 因为它就是最上层的控件了。
控件对象的 move 方法决定了这个控件显示的位置。 控件对象的 resize 方法决定了这个控件显示的大小。
放在主窗口的控件要能全部显示在界面上 必须使用window.show()
最后 通过app.exec_()进入QApplication的事件处理循环接收用户的输入事件并且分配给相应的对象去处理。 常用控件介绍https://www.byhy.net/tut/py/gui/qt_05_1/
1.2 动作 (signal 和 slot)
在 Qt 系统中 当界面上一个控件被操作时比如 被点击、被输入文本、被鼠标拖拽等 就会发出 信号signal 。就是表明一个事件发生了比如被点击、被输入文本。
我们可以预先在代码中指定处理这个 signal 的函数这个处理 signal 的函数 叫做 槽slot 。
比如上节例子中我们可以像下面这样定义一个slot函数
def handleCalc():QMessageBox.about(window, 关于, 点击按钮1次)QMessageBox是的信息提示框对象他的about方法可以单独弹出一个提示框。
然后 指定 如果 发生了button 按钮被点击 的事情需要让 handleCalc 来处理像这样
button.clicked.connect(handleCalc)用QT的术语来解释上面这行代码就是把 button 被点击(clicked)产生的信号signal 连接(connect)到了 handleCalc 这样的一个处理函数slot上。
大白话就是让 handleCalc 来 处理 button 被 点击的操作。
1.3 封装
上面的代码把控件对应的变量名全部作为全局变量。
如果要设计稍微复杂一些的程序就会出现太多的控件对应的变量名。
而且这样也不利于 代码的模块化。
所以我们通常应该把窗口和其包含的控件(self)以及处理函数对应的代码 全部封装到类中
import sys, os
import PySide2
from PySide2.QtWidgets import *
dirname os.path.dirname(PySide2.__file__)
plugin_path os.path.join(dirname, plugins, platforms)
os.environ[QT_QPA_PLATFORM_PLUGIN_PATH] plugin_path
print(plugin_path)class Stats():def __init__(self):self.window QMainWindow()self.window.resize(500, 400)self.window.move(300, 300)self.window.setWindowTitle(窗口名)self.textEdit QPlainTextEdit(self.window)self.textEdit.setPlaceholderText(文本框默认内容)self.textEdit.move(10, 25)self.textEdit.resize(300, 350)self.button QPushButton(按钮名, self.window)self.button.move(380, 80)self.button.clicked.connect(self.handleCalc)def handleCalc(self):QMessageBox.about(self.window, 关于, 点击按钮1次)app QApplication([])
stats Stats()
stats.window.show()
app.exec_()2 界面布局
2.1 Qt Designer
我们可以用QT界面生成器 Qt Designer 拖拖拽拽就可以直观的创建出程序大体的界面。
怎么运行这个工具呢
Windows下运行 Python安装目录下 Scripts\pyside2-designer.exe 这个可执行文件 如果你安装的是pyqt5 运行 Python安装目录下 Scripts\pyqt5designer.exe 这个可执行文件。
主界面区域介绍
工具箱 区域提供GUI界面开发使用的各种基本控件如单选框、文本框等。可以拖动到新创建的主程序界面。
主界面 区域用户放置各种从工具箱拖过来的各种控件。模板选项中最常用的就是Widget通用窗口和MainWindow主窗口。二者区别主要是Widget窗口不包含菜单栏、工具栏等。可以分别创建对比看看。
对象查看器 区域查看主窗口放置的对象列表。
属性编辑器 区域 提供对窗口、控件、布局的属性编辑功能。比如修改控件的显示文本、对象名、大小等。
信号/槽编辑器 区域编辑控件的信号和槽函数也可以添加自定义的信号和槽函数。 Widget Box控件工具箱介绍
窗体Window Mian Window(包含菜单栏的窗体)Widget(不包含菜单栏的窗体)显示控件(Display Widget) Lable文本标签显示文本可以用来标记控件。PySide2 中QLabel类可以显示文字和图片选择了QLabel加Timer播放。QLabel显示的格式必须是Qimage,但是用cv2读取的帧格式是numpy array必须把它转换成为Qimage。Text Browser显示文本控件。用于后台命令执行结果显示。输入控件(Input Widget)提供与用户输入交互 Line Edit单行文本框输入单行字符串。控件对象常用函数为Text() 返回文本框内容用于获取输入。setText() 用于设置文本框显示。Text Edit多行文本框输入多行字符串。控件 对象常用函数同Line Edit控件。Combo Box下拉框列表。用于输入指定枚举值。控件按钮(Buttons)供用户选择与执行 Push Button命令按钮。常见的确认、取消、关闭等按钮就是这个控件。clicked信号一定要记住。clicked信号就是指鼠标左键按下然后释放时会发送信号从而触发相应操作。Radio Button单选框按钮。Check Box多选框按钮。布局(Layout)不同布局方式可以嵌套比如A是水平布局B是垂直布局 可以选中AB再做一种布局方式参考讲解Layout 布局有三种方法 1、先在左侧空间栏Layouts中的某种布局方式拖动到主窗口再将组件拖入布局窗中 2、先将组件拖入主窗中并选中再点击工具栏中的某种布局方式如下图。 3、先将组件拖入主窗中并选中鼠标右键布局,选择其中一种布局方式。 所有组件的布局完成之后如下图红色框位置顶层还未布局选中顶层然后对其进行布局。可以进行水平、垂直、网格的任意一种效果一样。至此已经完成了所有布局按CTRLR预览的时候拉大窗口所有组件会随着窗口的变化而变化。
间隔(Spacers)实现部件布局排列美观如自动靠左对齐或者靠右对齐的方式来显示等。Spacers部件除了名字之外只有三个属性分别是orientation、sizeType和sizeHint。
属性编辑器介绍 有从父类Widget继承而来的属性也有自己控件独特的属性比较方便。 常用的属性介绍
名称含义objectName控件对象名称geometry相应左上角为原点的坐标与宽和高x,y,x,ysizePolicy控件大小的策略minimumSize最小的宽和高maximumSize最大的宽和高font字体cursor光标…………
导出设计
通过 Qt Designer 设计的界面最终是生成XML格式的ui界面定义文件。
2.2 动态加载UI文件(推荐) 有了界面定义文件我们的Python程序就可以从文件中加载UI定义并且动态 创建一个相应的窗口对象。
如下
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import *
dirname os.path.dirname(PySide2.__file__)
plugin_path os.path.join(dirname, plugins, platforms)
os.environ[QT_QPA_PLATFORM_PLUGIN_PATH] plugin_path
print(plugin_path)class Stats:def __init__(self):# 从文件中加载UI定义self.ui QUiLoader().load(你的UI文件名.ui)# 从 UI 定义中动态 创建一个相应的窗口对象# 注意里面的控件对象也成为窗口对象self.ui的属性了# 比如 self.ui.button , self.ui.textEditself.ui.button.clicked.connect(self.handleCalc)def handleCalc(self):QMessageBox.about(self.window, 关于, 点击按钮1次)app QApplication([])
stats Stats()
stats.ui.show()
app.exec_()2.3 转化UI文件为Python代码(不推荐)
先把UI文件直接转化为包含界面定义的Python代码文件然后在你的程序中使用定义界面的类执行如下的命令 把UI文件直接转化为包含界面定义的Python代码文件。
pyside2-uic main.ui ui_main.py然后在你的代码文件中这样使用定义界面的类
from PySide2.QtWidgets import QApplication,QMainWindow
from ui_main import Ui_MainWindow# 注意 这里选择的父类 要和你UI文件窗体一样的类型
# 主窗口是 QMainWindow 表单是 QWidget 对话框是 QDialog
class MainWindow(QMainWindow):def __init__(self):super().__init__()# 使用ui文件导入定义界面类self.ui Ui_MainWindow()# 初始化界面self.ui.setupUi(self)# 使用界面定义的控件也是从ui里面访问self.ui.webview.load(http://www.baidu.com)app QApplication([])
mainw MainWindow()
mainw.show()
app.exec_()通常采用动态加载比较方便因为改动界面后不需要转化直接运行特别方便。
3 显示样式
要让产品更好看一些通常就是指定界面元素的 显示样式 。比如指定颜色、字体、间距。Qt有种定义界面显示样式的方法称之为 Qt Style Sheet 简称 QSS。
如果在设计师界面上 最上层的 MainWindow 对象 styleSheet 属性指定如下的内容
QPushButton { color: red ;font-size:15px;
}就会发现所有的按钮上的文字都变成了红色的并且字体变大了。注意这个指定界面元素 显示样式的 语法由 selector 和 declaration 组成。
花括号前面的 部分比如示例中的 QPushButton 称之为 selector。花括号后面的 部分称之为 Properties样式属性。
选择器selector花括号前面的 部分称之为 selector用来 告诉Qt 哪些特征的元素 是你要设定显示效果的。
样式属性declaration在Qt Designer中设置样式。
背景可以指定某些元素的背景色像这样
QTextEdit { background-color: yellow }颜色可以使用红绿蓝数字像这样
QTextEdit { background-color: #e7d8d8 }也可以像这样指定背景图片
QTextEdit {background-image: url(gg03.png);
}边框可以像这样指定边框
border:1px solid #1d649c;其中1px 是边框宽度solid 是边框线为实线 也可以是 dashed(虚线) 和 dotted点 比如
*[myclassbar2btn]:hover{border:1px solid #1d649c;
}边框可以指定为无边框
border:none字体、大小、颜色可以这样指定元素的 文字字体、大小、颜色
*{ font-family:微软雅黑;font-size:15px;color: #1d649c;
}宽度、高度可以这样指定元素的 宽度、高度
QPushButton { width:50px;height:20px;
}margin、padding 可以这样指定元素的 元素的 margin分别指定了元素的上右下左margin。
QTextEdit {margin:10px 11px 12px 13px
}也可以使用 margin-top, margin-right, margin-bottom, margin-left 单独指定 元素的上右下左margin。
QTextEdit {margin:10px 50px;padding:10px 50px;
}4 后台线程 与 信号
4.1 界面阻塞问题
我们 点击按钮 执行槽函数如果服务端接收处理的比较慢就会导致槽函数要比较长的时间才能返回。假设10秒钟后才接收到响应消息这时候界面就会 僵死 10秒钟。
这是因为我们现在的代码都是在主线程中执行的。其中最末尾的代码
app.exec_()其实会让主线程进入一个死循环循环不断的处理 用户操作的事件。
当我们点击按钮后Qt的 核心代码就会接受到这个 点击事件并且调用相应的 slot函数去处理。
因为我们代码做了这样的设置
# 信号处理
self.ui.buttonSend.clicked.connect(self.槽函数)如果这个槽函数很快能接收到 服务端的响应那么 槽函数 就可以很快的返回。
返回后 整个程序又进入到 app.exec_() 里面接收各种 事件并且调用相应的函数去处理。界面就不会僵死因为所有的操作界面的事件都能得到及时的处理。
但是如果这个 槽函数 要很长时间才能返回这段时间内整个程序就停在 槽函数内的某段代码处自然就没有机会去处理其他的用户操作界面的事件了当然程序就僵死了。
4.2 子线程处理
典型的一种解决方法就是使用多线程去处理。
为了防止槽函数卡在 发送请求 或 处理数据的操作上我们可以使用Python多线程将发送请求 或 处理数据的操作封装成一个函数在槽函数中创建新线程然后调用封装好的函数。
这样通过创建新的线程去执行[发送请求 或 处理数据]的方法服务器响应再慢也只会在新线程中阻塞主线程启动新线程后主线程就继续执行后面的代码返回继续运行Qt的事件循环处理 可以响应用户的操作就不会僵死了。
from threading import Threaddef 槽函数(self)正常操作;# 创建新的线程去执行发送方法# 服务器慢只会在新线程中阻塞# 不影响主线程thread Thread(target self.新线程请求或处理函数,args (参数列表))thread.start()# 新线程入口函数def 新线程请求或处理函数(self,参数列表):原来槽函数中 发送请求 或 处理数据的操作;4.3 子线程发信号更新界面
Qt建议 只在主线程中操作界面 。
在另外一个线程直接操作界面可能会导致意想不到的问题比如输出显示不全甚至程序崩溃。
但是我们确实经常需要在子线程中 更新界面。比如子线程是个爬虫爬取到数据显示在界面上。
怎么办呢
这时推荐的方法是使用信号。
前面我们曾经看到过 各种 Qt 控件可以发出信号比如 被点击、被输入等。
我们也可以自定义信号只要这个类继承QObject类就能发出自己定义的各种Qt信号具体做法如下 自定义一个Qt 的 QObject类里面封装一些自定义的 Signal信号一种信号定义为 该类的 一个 静态属性值为Signal 实例对象即可。可以定义 多个 Signal静态属性对应这种类型的对象可以发出的 多种 信号。 (如下MySignals类有text_print 信号 和 update_table 信号) 注意Signal实例对象的信号参数类型就是 发出信号对象时传递的参数数据类型。因为Qt底层是C开发的必须指定类型。(如下的QTextBrowser 和 str类型) 定义主线程执行的函数处理Signal信号通过connect方法 在新线程需要操作界面的时候就通过自定义对象 发出 信号 通过该信号对象的 emit方法发出信号 emit方法的参数 传递必要的数据。参数类型 遵循 定义Signal时指定的类型。 主线程信号处理函数被触发执行获取Signal里面的参数执行必要的更新界面操作
from PySide2.QtWidgets import QApplication, QTextBrowser
from PySide2.QtUiTools import QUiLoader
from threading import Threadfrom PySide2.QtCore import Signal,QObject# 自定义信号源对象类型一定要继承自 QObject
class MySignals(QObject):# 定义一种text_print信号两个参数 类型分别是 QTextBrowser 和 字符串# 调用 emit方法 发信号时传入参数 必须是这里指定的 参数类型text_print Signal(QTextBrowser,str)# 还可以定义其他种类的update_table信号update_table Signal(str)# 实例化
global_ms MySignals() # GUI类
class Stats:def __init__(self):self.ui QUiLoader().load(main.ui)# 自定义信号MySignals类的处理函数global_ms.text_print.connect(self.printToGui)# 自定义信号处理函数def printToGui(self,fb,text):fb.append(str(text))fb.ensureCursorVisible()# 产生text_print信号时的界面操作函数def task1(self):def threadFunc():# 通过Signal 的 emit 触发执行 主线程里面的处理函数# emit参数和定义Signal的数量、类型必须一致global_ms.text_print.emit(self.ui.infoBox1, 输出内容)thread Thread(target threadFunc )thread.start()
5 智云平台实战
智云平台是一个集成活体检测、人脸识别、关键点检测、人像分割、疲劳检测、视线追踪、微表情识别、危险驾驶动作识别、火灾检测、越狱检测、打架检测的开放算法平台。
待更…
程序图标
添加主窗口图标 我们程序运行的窗口需要显示自己的窗口图标这样才更像一个正式的产品。
通过如下代码我们可以把一个png图片文件作为 程序窗口图标。
from PySide2.QtGui import QIconapp QApplication([])
# 加载 icon
app.setWindowIcon(QIcon(logo.png))注意这些图标png文件在使用PyInstaller创建可执行程序时也要拷贝到程序所在目录。否则可执行程序运行后不会显示图标。
应用程序图标 应用程序图标是放在可执行程序里面的资源。可以在PyInstaller创建可执行程序时通过参数 --icon“logo.ico” 指定。
pyinstaller main_ui.py --noconsole --hidden-import PySide2.QtXml --iconlogo.ico注意参数一定是存在的ico文件不能是png等图片文件。
如果你只有png文件可以通过在线的png转ico文件网站生成ico比如下面的网站IOC生成
发布程序
我们前面开发的QT界面程序在Windows 上只需要执行pyinstaller 的命令即可制作独立exe程序。
pyinstaller main_ui.py --noconsole --hidden-import PySide2.QtXml这样就会在当前目录下产生一个名为 dist 的目录dist目录里面就有一个名为 main_ui的目录我们的可执行程序 main_ui.exe 就在里面。
main_ui.py
dis____|main_ui____|main_ui.exe其中 main_ui.py是包含QApplication()的GUI程序可以自己命名。 noconsole 指定不要命令行窗口否则我们的程序运行的时候还会多一个黑窗口。 但是我建议大家可以先去掉这个参数等确定运行成功后再加上参数重新制作exe。因为这个黑窗口可以显示出程序的报错这样我们容易找到问题的线索。 hidden-import PySide2.QtXml 参数是因为这个 QtXml库是动态导入PyInstaller没法分析出来需要我们告诉它。
最后如果使用的是动态加载UI文件别忘了把程序所需要的ui文件拷贝到main_ui.exe同级目录中。
因为PyInstaller只能分析出需要哪些代码文件。 而你的程序动态打开的资源文件比如 图片、excel、ui这些它是不会帮你打包的。