基于PyQt5的开发项目,代码小结。
项目界面比较简单,只使用了基础部分,没有使用QML、Qt Quick等高级用法。
系统环境
硬件:树莓派3B+
软件:
- Python 3.5.3
- PyQt 5.7.1(环境安装:
sudo apt-get insatll python3-pyqt5
) - PyQt 5.14.2(环境安装:pip3 install PyQt5==5.14.2(python setup.py egg_info error 解决))
硬件环境:Windows 10
软件:
Hello World
1 | #!/usr/bin/python3 |
示例代码运行会在屏幕上显示一个小窗体,如下:
QApplication
QApplication类管理GUI程序控制流和主要设置。包含处理本程序和其他来源的事件循环,程序的初始化和结束,并提供对话管理。QApplication处理了系统和应用的大部分设置。
对于用Qt写的任何一个GUI应用,不管这个应用有没有窗口或多少个窗口,有且只有一个QApplication对象,QApplication对象必须在绘制设备(设备包括窗口、像素映射、位图等)之前创建。
而对于用Qt写的非GUI应用,则有且只有一个QCoreApplication对象,并且这个应用不依赖QtGui库。
QApplication.exec_(),开始事件循环,直到exit()被调用。
MainWindow
MainWindow是一个继承了QWidget的类,QWidget是所有控件的父类,如QLabel、QButton等,当它的父类为空时,它是一个Window,这个窗体本身就用很多属性和方法,如长宽、在屏幕中的位置等,可以使用setGeometry()来设置,除此之外,还用一下方法使用得比较多:
方法 | 释义 |
---|---|
setGeometry(w, h, x, y) | 设置长宽为w,h,移动到x,y坐标 |
QRect geometry() | 获取长宽和坐标,QRect 使用width()、height()、x()、y()方法获得单个值 |
size() | 获取窗体长宽 |
resize(w, h) | 设置长宽为w,h |
setFixedSize(w,h) | 设置为长宽不可变的窗体 |
move(x, y) | 移动到x,y坐标 |
setCursor() | 设置鼠标样式 |
setWindowTitle(string) | 设置窗口标题 |
setWindowIcon(QIcon) | 设置窗口图标 |
setWindowFlags(WindowFlags) | 设置窗口样式 |
setStyleSheet(string) | 设置窗口样式表 |
setLayout(QLayout) | 设置当前界面的布局管理器 |
show() | 在每次布局完,调用show来显示 |
showFullScreen() | 全屏显示 |
close() | 关闭部件 |
窗体类型
本例中,继承的是QWidget,初此之外,还有这些窗体类型:
- Qt.Widget:这是QWidget的默认类型。如果它们有父级,这种类型的部件是子部件,如果没有父控件,则为独立窗口。
- Qt.Window:表示小部件是一个窗口,无论窗口小部件是否具有父控件,通常具有窗口系统框架和标题栏。如果部件没有父控件,则无法取消设置此标记(即如果存在父控件,则可以取消此标记,否则,必须存在此标记用以标识此控件是个独立窗口)。
- Qt.Dialog:指示部件是应该作为对话框窗口(即标题栏中通常没有最大化或最小化按钮)。这是QDialog的默认类型。如果要将其用作模态对话框,则应从另一个窗口启动它,或者如果有父窗口,则与QWidget.windowModality属性一起使用。如果将其设置为模态,则对话框将阻止应用程序中的其他顶级窗口获取任何输入。我们将具有父级的顶级窗口称为辅助窗口。
- Qt.Sheet:表示该窗口是Macintosh工作表。 由于使用工作表意味着窗口模态,推荐的方法是使用QWidget.setWindowModality()或QDialog.open()。
- Qt.Drawer:表示该窗口小部件是Macintosh抽屉。
- Qt.Popup:表示窗口小部件是弹出式顶级窗口,即它是模态的,但具有适合弹出菜单的窗口系统框架。
- Qt.Tool:表示窗口小部件是工具窗口。工具窗口通常是一个小窗口,其标题栏和装饰比通常小,通常用于工具按钮的集合。 如果有父部件,则工具窗口将始终保持在其上。 如果没有父部件,您可以考虑使用Qt.WindowStaysOnTopHint使其位于最顶端。 如果窗口系统支持它,工具窗口可以用更轻的框架装饰。它也可以与Qt.FramelessWindowHint结合使用。 在macOS上,工具窗口对应浮动类窗口。 这意味着窗口存在于正常窗口之上; 不可能在它上面放一个普通的窗口。 默认情况下,当应用程序处于非活动状态时,工具窗口将消失。 这可以通过Qt.WA_MacAlwaysShowToolWindow属性来控制。
- Qt.ToolTip:表示窗口小部件是工具提示。 这在内部用于实现工具提示,没有标题栏和窗口边框。
- Qt.SplashScreen:表示该窗口是闪屏。 这是QSplashScreen的默认类型。
- Qt.Desktop:表示此小组件是桌面。 这是QDesktopWidget的类型。
- Qt.SubWindow:表示此窗口小部件是子窗口,例如QMdiSubWindow窗口小部件。
- Qt.ForeignWindow:指示此窗口对象是表示由另一个进程创建的本机平台窗口或手动使用本机代码的句柄。
- Qt.CoverWindow:表示该窗口代表一个封面窗口,例如,当应用程序在BlackBerry平台上最小化时显示。
- Qt.MSWindowsFixedSizeDialogHint:在Windows上为窗口提供精简的对话框边框。 此样式传统上用于固定大小的对话框。
- Qt.MSWindowsOwnDC:在Windows上为窗口提供自己的显示上下文。
- Qt.BypassWindowManagerHint:此标志可用于向平台插件指示应禁用“所有”窗口管理器协议。 此标志的行为会有所不同,具体取决于运行应用程序的操作系统以及正在运行的窗口管理器。 该标志可用于获取没有配置集的本机窗口。
- Qt.X11BypassWindowManagerHint:完全绕过窗口管理器。 这导致无边界窗口根本不受管理(即,除非您手动调用QWidget.activateWindow(),否则没有键盘输入)。
- Qt.FramelessWindowHint:生成无边框窗口。 用户无法通过窗口系统移动或调整无边框窗口的大小。 在X11上,标志的结果取决于窗口管理器及其理解Motif和/或NETWM提示的能力。 大多数现有的窗口管理器都可以处理。
- Qt.NoDropShadowWindowHint:在支持平台上禁用窗口投影。
Qt.WindowFlags
Qt.WindowFlags是一个32位的参数,设置此属性时,可以将多个属性进行与或来得到想要的窗口效果。
主要的窗口样式:
1 | Qt::CustomizeWindowHint //关闭默认窗口标题提示 |
各种组合的样式参照:https://www.cnblogs.com/Jace-Lee/p/5869496.html
布局管理
Hello World示例显示了一个窗体,但我们使用图形界面的目的当然不是只显示一个窗体,而是要放入字符标签和按钮等元素。如何按照我们的意愿放置元素便是布局管理做的事情。
具体分为绝对布局、横向/纵向布局、表格布局,详情可参见PyQt5布局管理。
QSS
加载样式表
1 | # 方在initUI里,调用show之前 |
QLabel显示图片并缩放
QLabel(pixmap = QPixmap("logo.png").scaled(155,48))
Title背景效果
显示效果:
1 | #!/usr/bin/python3 |
圆形图片按钮
素材如下:
1 | # *.py |
按钮图片切换
1 | # *.py |
表格样式
QTableWidget效果:
*.py:
1 | #!/usr/bin/python3 |
QSS:
1 | /* table_test.qss */ |
QHeaderView.Stretch模式会根据表的宽度均分设置每列的宽度,但实际中每列的长度是有差异的,且如果每列数据的长度基本一致,可以设置列宽模式为固定的,如上表设置成这样会更合理一些:
1 | self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed) |
日期样式
样式效果:
1 | self.dt_time = QDateTimeEdit(QDate().currentDate()) |
QSS:
1 | QDateTimeEdit { |
左右箭头素材:
异步加载并显示数据
需要从服务器拉取数据,并显示。如果和服务器交互需要比较长的时间,就会造成界面卡顿,我们就必须选择异步加载。
如下,是一个异步显示数据的一个例子,点击“加载数据”按钮,会开启一个线程,线程用户可以将获取到的数据发送给界面,由主线程控制显示,这样就不会阻塞主进程了。
1 | #!/usr/bin/python3 |
新建了一个QThread类,声明了一个pyqtSignal成员,pyqtSignal的类型根据所要传输数据的类型而定,在主线程中绑定响应函数,最后在loadThread线程中调用emit就发送到主线程了。
显示动画
Loading动画:
1 | # 加载loading动画 |
自定义MessageBox
原始的QMessageBox样式比较难看,所以使用QDialog封装一个自定义的消息弹窗,自定义显示标题、消息、按钮三个部分,其中标题、消息为字符串,按钮传入QMessageBox.Yes|QMessageBox.No对应显示确定/取消,只传入其中一个则只显示一个按钮。
效果:
使用自定义MessageBox:
1 | #!/usr/bin/python3 |
具体实现:messagebox.py
1 | # messagebox.py |
具体实现:messagebox.qss:
1 | QDialog { |
参考链接:
- PyQt5教程
- Qt for Python Modules(Qt Widgets中包含所有控件的操作方法和详细说明)
- Qt Style Sheets Reference
- Qt Style Sheets Examples