PyQt5 - 快速指南


PyQt5 - 简介

PyQt 是一个 GUI 小部件工具包。它是Qt的 Python 接口,Qt 是最强大、最流行的跨平台 GUI 库之一。PyQt由RiverBankComputing Ltd开发。最新版本的PyQt可以从其官方网站下载 - Riverbankcomputing.com

PyQt API 是一组包含大量类和函数的模块。虽然QtCore模块包含用于处理文件和目录等的非 GUI 功能,但QtGui模块包含所有图形控件。此外,还有用于处理 XML (QtXml)、SVG (QtSvg)和 SQL (QtSql)等的模块。

下面给出了常用模块的列表 -

  • QtCore - 其他模块使用的核心非 GUI 类

  • QtGui - 图形用户界面组件

  • QtMultimedia - 低级多媒体编程类

  • QtNetwork - 网络编程类

  • QtOpenGL - OpenGL 支持类

  • QtScript - 用于评估 Qt 脚本的类

  • QtSql - 使用 SQL 进行数据库集成的类

  • QtSvg - 用于显示 SVG 文件内容的类

  • QtWebKit - 用于渲染和编辑 HTML 的类

  • QtXml - 用于处理 XML 的类

  • QtWidgets - 用于创建经典桌面风格 UI 的类

  • QtDesigner - 用于扩展 Qt Designer 的类

支持环境

PyQt 与所有流行的操作系统兼容,包括 Windows、Linux 和 Mac OS。它具有双重许可,可根据 GPL 和商业许可使用。最新的稳定版本是PyQt5-5.13.2。

Windows

提供了适用于 32 位或 64 位架构的 Wheel,与 Python 3.5 或更高版本兼容。推荐的安装方法是使用PIP实用程序 -

pip3 install PyQt5

要安装 Qt Designer 等开发工具来支持 PyQt5 轮子,请执行以下命令 -

pip3 install pyqt5-tools

您还可以从源代码在 Linux/macOS 上构建 PyQt5 www.riverbankcomputing.com/static/Downloads/PyQt5

PyQt5 - 新增功能

PyQt5 API 不会自动与早期版本兼容。因此,涉及 PyQt4 模块的 Python 代码应通过进行相关更改来手动升级。本章列出了 PyQt4 和 PyQt5 之间的主要区别。

v2.6 之前的 Python 版本不支持 PyQt5。

PyQt5 不支持 QObject 类的 connect() 方法用于信号和槽之间的连接。因此无法再实施该用法 -

QObject.connect(widget, QtCore.SIGNAL(‘signalname’), slot_function)

仅定义以下语法 -

widget.signal.connect(slot_function)

早期 QtGui 模块中定义的类已分布在QtGui、QtPrintSupportQtWidgets模块中。

在新的 QFileDialog 类中,getOpenFileNameAndFilter()方法被getOpenFileName()替换, getOpenFileNamesAndFilter()被getOpenFileNames()替换,getSaveFileNameAndFilter()getSaveFileName() 替换。这些方法的旧签名也发生了变化。

PyQt5 没有提供定义从多个 Qt 类派生的类的规定。

pyuic5实用程序(从 Designer 的 XML 文件生成 Python 代码)不支持 --pyqt3-wrapper 标志。

Pyrcc5不支持 -py2 和 -py3 标志。Pyrcc5 的输出与 Python v2.6 及以后的所有版本兼容。

PyQt5 始终自动调用sip.setdestroyonexit()并调用它拥有的所有包装实例的 C++ 析构函数。

PyQt5 - 你好世界

使用 PyQt 创建一个简单的 GUI 应用程序涉及以下步骤 -

  • 从 PyQt5 包导入 QtCore、QtGui 和 QtWidgets 模块。

  • 创建 QApplication 类的应用程序对象。

  • QWidget 对象创建顶级窗口。在其中添加 QLabel 对象。

  • 将标签的标题设置为“hello world”。

  • 通过setGeometry()方法定义窗口的大小和位置。

  • 通过app.exec_()方法进入应用程序的主循环。

以下是在 PyQt 中执行 Hello World 程序的代码 -

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
def window():
   app = QApplication(sys.argv)
   w = QWidget()
   b = QLabel(w)
   b.setText("Hello World!")
   w.setGeometry(100,100,200,50)
   b.move(50,20)
   w.setWindowTitle("PyQt5")
   w.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   window()

上面的代码产生以下输出 -

你好世界

还可以开发上述代码的面向对象的解决方案。

  • 从 PyQt5 包导入 QtCore、QtGui 和 QtWidgets 模块。

  • 创建 QApplication 类的应用程序对象。

  • 基于QWidget类声明窗口类

  • 添加一个 QLabel 对象并将标签的标题设置为“hello world”。

  • 通过setGeometry()方法定义窗口的大小和位置。

  • 通过app.exec_()方法进入应用程序的主循环。

以下是面向对象解决方案的完整代码 -

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class window(QWidget):
   def __init__(self, parent = None):
      super(window, self).__init__(parent)
      self.resize(200,50)
      self.setWindowTitle("PyQt5")
      self.label = QLabel(self)
      self.label.setText("Hello World")
      font = QFont()
      font.setFamily("Arial")
      font.setPointSize(16)
      self.label.setFont(font)
      self.label.move(50,20)
def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   main()
你好世界

PyQt5 - 主要类

PyQt API是一个类和方法的大型集合。这些类在 20 多个模块中定义。

以下是一些常用模块 -

先生。 模块和描述
1

QtCore

其他模块使用的核心非 GUI 类

2

QtGUI

图形用户界面组件

3

Qt多媒体

低级多媒体编程类

4

Qt网络

网络编程类

5

QtOpenGL

OpenGL 支持类

6

Qt脚本

用于评估 Qt 脚本的类

7

QtSql

使用 SQL 进行数据库集成的类

8

QtSvg

用于显示 SVG 文件内容的类

9

QtWebKit

用于渲染和编辑 HTML 的类

10

QtXml

用于处理 XML 的类

11

QtWidgets

用于创建经典桌面风格 UI 的类。

12

Qt设计器

用于扩展 Qt Designer 的类

13

Qt助手

支持在线帮助

PyQt5 开发工具是用于 Qt 开发的有用实用程序的集合。以下是此类实用程序的精选列表 -

先生。 工具名称和说明
1

助手

Qt Assistant 文档工具

2

pyqt5设计器

Qt Designer GUI 布局工具

3

语言学家

Qt Linguist 翻译工具

4

释放

将ts文件编译为qm文件

5

pyupdate5

提取翻译字符串并生成或更新 ts 文件

6

qmake

Qt 软件构建工具

7

pyqt5qml场景

QML 文件查看器

8

pyqml查看器

QML 文件查看器

9

吡啶5

Qt资源文件编译器

10

pyuic5

Qt 用户界面编译器,用于从 ui 文件生成代码

11

pyqmltestrunner

在 QML 代码上运行单元测试

12

总线

用于列出 D-Bus 服务的命令行工具

13

量子文档

软件项目的文档生成器。

14

Qhelp生成器

生成和查看 Qt 帮助文件。

15

qml导入扫描器

解析并报告 QML 导入

PyQt API 包含 400 多个类。QObject类位于类层次结构顶部。它是所有 Qt 对象的基类。此外,QPaintDevice类是所有可绘制对象的基类。

QApplication类管理 GUI 应用程序的主要设置和控制流程。它包含主事件循环,在其中处理和调度由窗口元素和其他源生成的事件。它还处理系统范围和应用程序范围的设置。

QWidget类派生自 QObject 和 QPaintDevice 类,是所有用户界面对象的基类。QDialogQFrame类也派生自 QWidget 类。他们有自己的子类系统。

这是常用小部件的精选列表

先生。 小部件和描述
1

Q标签

用于显示文本或图像

2

QLine编辑

允许用户输入一行文本

3

QText编辑

允许用户输入多行文本

4

Q按钮

用于调用操作的命令按钮

5

Q单选按钮

允许从多个选项中选择一个

6

Q复选框

允许选择多个选项

7

QSpinBox

允许增加/减少整数值

8

Q滚动条

允许访问显示孔径之外的小部件的内容

9

Q滑块

能够线性改变界限值。

10

QComboBox

提供可供选择的项目的下拉列表

11

Q菜单栏

包含 QMenu 对象的单杠

12

Q状态栏

通常在 QMainWindow 的底部,提供状态信息。

13

Q工具栏

通常位于 QMainWindow 的顶部或浮动。包含操作按钮

14

QListView

以 ListMode 或 IconMode 提供可选择的项目列表

15

Q像素图

用于在 QLabel 或 QPushButton 对象上显示的离屏图像表示

16

QDialog

可以向父窗口返回信息的模态或非模态窗口

典型的基于 GUI 的应用程序的顶级窗口是由QMainWindow小部件对象创建的。上面列出的一些小部件在此主窗口中占据指定位置,而其他小部件则使用各种布局管理器放置在中央小部件区域中。

下图显示了 QMainWindow 框架 -

Q主窗口

PyQt5 - 使用 Qt 设计器

PyQt 安装程序附带一个名为Qt Designer 的GUI 构建工具。使用其简单的拖放界面,可以快速构建 GUI 界面,而无需编写代码。但是,它不是 Visual Studio 等 IDE。因此,Qt Designer 不具备调试和构建应用程序的功能。

启动 Qt Designer 应用程序,它是开发工具的一部分,安装在虚拟环境的脚本文件夹中。

虚拟环境

通过选择“文件”→“新建”菜单开始设计 GUI 界面。

新菜单

然后,您可以从左侧窗格的小部件框中拖放所需的小部件。您还可以为表单上放置的小部件的属性分配值。

小部件

设计好的表单保存为demo.ui。该 ui 文件包含小部件及其在设计中的属性的 XML 表示形式。使用 pyuic5 命令行实用程序将此设计转换为 Python 等效项。该实用程序是 Qt 工具包的 uic 模块的包装器。pyuic5 的用法如下 -

pyuic5 -x demo.ui -o demo.py

在上面的命令中,-x 开关向生成的 Python 脚本(来自 XML)添加少量附加代码,使其成为可自执行的独立应用程序。

if __name__ == "__main__":
   import sys
   app = QtGui.QApplication(sys.argv)
   Dialog = QtGui.QDialog()
   ui = Ui_Dialog()
   ui.setupUi(Dialog)
   Dialog.show()
   sys.exit(app.exec_())

执行生成的 python 脚本以显示以下对话框 -

python demo.py
对话框

用户可以在输入字段中输入数据,但单击“添加”按钮不会生成任何操作,因为它不与任何功能关联。对用户生成的响应做出反应称为事件处理

PyQt5 - 信号和槽

与以顺序方式执行的控制台模式应用程序不同,基于 GUI 的应用程序是事件驱动的。函数或方法的执行是为了响应用户的操作,例如单击按钮、从集合中选择项目或单击鼠标等,称为事件

用于构建 GUI 界面的小部件充当此类事件的源。每个 PyQt 小部件都派生自 QObject 类,旨在发出“信号”以响应一个或多个事件。该信号本身不执行任何操作。相反,它“连接”到“插槽”。该槽可以是任何可调用的 Python 函数

使用 Qt Designer 的信号/槽编辑器

首先设计一个带有 LineEdit 控件和 PushButton 的简单窗体。

老虎机编辑器

希望如果按下按钮,文本框的内容应该被删除。QLineEdit 小部件有一个用于此目的的clear() 方法。因此,按钮的单击信号将连接到文本框的clear()方法。

首先,从编辑菜单中选择编辑信号/时隙(或按 F4)。然后用鼠标突出显示按钮并将光标拖向文本框

光标

释放鼠标时,将显示一个对话框,显示按钮信号和插槽方法。选择点击信号和clear()方法

清除方法

右下角的信号/槽编辑器窗口将显示结果 -

编辑器窗口

从 ui 文件中保存 ui 和 Build 以及 Python 代码,如下面的代码所示 -

pyuic5 -x signalslot.ui -o signalslot.py

生成的 Python 代码将通过以下语句在信号和槽之间建立连接 -

self.pushButton.clicked.connect(self.lineEdit.clear)

运行 Signalslot.py 并在 LineEdit 中输入一些文本。如果按下按钮,文本将被清除。

构建信号槽连接

您可以不使用 Designer,而是通过以下语法直接建立信号槽连接 -

widget.signal.connect(slot_function)

假设单击按钮时是否要调用一个函数。在这里,单击的信号将连接到可调用的函数。它可以通过以下任何技术来实现 -

button.clicked.connect(slot_function)

例子

在下面的示例中,两个 QPushButton 对象(b1 和 b2)被添加到 QDialog 窗口中。我们希望在单击 b1 和 b2 时分别调用函数 b1_clicked() 和 b2_clicked()。

单击 b1 时,clicked() 信号将连接到 b1_clicked() 函数 -

b1.clicked.connect(b1_clicked())

当单击 b2 时,clicked() 信号将连接到 b2_clicked() 函数。

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   win = QDialog()
   b1 = QPushButton(win)
   b1.setText("Button1")
   b1.move(50,20)
   b1.clicked.connect(b1_clicked)
   
   b2 = QPushButton(win)
   b2.setText("Button2")
   b2.move(50,50)
   b2.clicked.connect(b2_clicked)
   
   win.setGeometry(100,100,200,100)

   win.setWindowTitle("PyQt5")
   win.show()
   sys.exit(app.exec_())

def b1_clicked():
   print ("Button 1 clicked")

def b2_clicked():
   print ("Button 2 clicked")

if __name__ == '__main__':
   window()

上面的代码产生以下输出 -

按钮

输出

Button 1 clicked
Button 2 clicked

PyQt5 - 布局管理

通过指定以像素为单位的绝对坐标,可以将 GUI 小部件放置在容器窗口内。坐标与 setGeometry() 方法定义的窗口尺寸相关。

setGeometry() 语法

QWidget.setGeometry(xpos, ypos, width, height)

在以下代码片段中,尺寸为 300 x 200 像素的顶级窗口显示在监视器上的位置 (10, 10)。

import sys
from PyQt4 import QtGui

def window():
   app = QtGui.QApplication(sys.argv)
   w = QtGui.QWidget()
	
   b = QtGui.QPushButton(w)
   b.setText("Hello World!")
   b.move(50,20)
	
   w.setGeometry(10,10,300,200)
   w.setWindowTitle(“PyQt”)
   w.show()
   sys.exit(app.exec_())
	
if __name__ == '__main__':
   window()

PushButton小部件将添加到窗口中,并放置在窗口右侧 50 像素、左上方下方 20 像素的位置。

然而,由于以下原因,这种绝对定位并不合适 -

  • 即使调整窗口大小,小部件的位置也不会改变。

  • 在具有不同分辨率的不同显示设备上,外观可能不统一。

  • 布局的修改很困难,因为可能需要重新设计整个表单。

原始窗口和调整大小的窗口

PyQt API 提供布局类,以便更优雅地管理容器内小部件的定位。布局管理器相对于绝对定位的优点是 -

  • 窗口内的小部件会自动调整大小。

  • 确保不同分辨率的显示设备上的外观一致。

  • 无需重新设计即可动态添加或删除小部件。

Qt 工具包定义了可与 Qt Designer 实用程序一起使用的各种布局。

显示类

这是我们将在本章中一一讨论的类列表。

先生。 类别和描述
1 QBox布局

QBoxLayout 类垂直或水平排列小部件。它的派生类是QVBoxLayout(用于垂直排列小部件)和QHBoxLayout(用于水平排列小部件)。

2 QGrid布局

GridLayout 类对象呈现按行和列排列的单元格网格。该类包含 addWidget() 方法。可以通过指定单元格的行数和列数来添加任何小部件。

3 QForm布局

QFormLayout 是创建两列表单的便捷方法,其中每行包含一个与标签关联的输入字段。按照惯例,左列包含标签,右列包含输入字段。

PyQt5 - 基本小部件

这是我们将在本章中一一讨论的小部件列表。

先生编号 小部件和描述
1 Q标签

QLabel 对象充当占位符来显示不可编辑的文本或图像,或者动画 GIF 的电影。它还可以用作其他小部件的助记键。

2 QLine编辑

QLineEdit对象是最常用的输入字段。它提供了一个可以在其中输入一行文本的框。为了输入多行文本,需要 QTextEdit 对象。

3 Q按钮

在 PyQt API 中,QPushButton 类对象呈现一个按钮,单击该按钮时可以对其进行编程以调用特定功能。

4 Q单选按钮

QRadioButton 类对象提供带有文本标签的可选按钮。用户可以选择表单上呈现的众多选项之一。该类派生自 QAbstractButton 类。

5 Q复选框

当 QCheckBox 对象添加到父窗口时,文本标签之前会出现一个矩形框。就像QRadioButton一样,它也是一个可选择的按钮。

6 QComboBox

QComboBox 对象呈现一个可供选择的项目的下拉列表。仅显示当前选定的项目所需的表单上所需的最小屏幕空间。

7 QSpinBox

QSpinBox 对象向用户呈现一个文本框,该文本框显示一个整数,右侧带有向上/向下按钮。

8 QSlider 小部件和信号

QSlider 类对象向用户提供了一个可以在其上移动手柄的凹槽。它是一个控制有界值的经典小部件。

9 QMenuBar、QMenu 和 QAction

QMainWindow 对象标题栏正下方的水平 QMenuBar 保留用于显示 QMenu 对象。

10 Q工具栏

QToolBar 小部件是一个可移动面板,由文本按钮、带有图标的按钮或其他小部件组成。

11 Q输入对话框

这是一个预配置的对话框,带有一个文本字段和两个按钮:“确定”和“取消”。用户单击“确定”按钮或按 Enter 键后,父窗口会收集文本框中的输入。

12 Q字体对话框

另一个常用的对话框,字体选择器小部件是 QDialog 类的视觉外观。该对话框的结果是一个 Qfont 对象,可以由父窗口使用。

13 Q文件对话框

该小部件是一个文件选择器对话框。它使用户能够浏览文件系统并选择要打开或保存的文件。该对话框可以通过静态函数或通过调用对话框对象上的 exec_() 函数来调用。

14 Q选项​​卡

如果表单有太多字段无法同时显示,则可以将它们排列在位于选项卡式小部件的每个选项卡下的不同页面中。QTabWidget 提供了一个选项卡栏和一个页面区域。

15 Q堆叠

QStackedWidget 的功能与 QTabWidget 类似。它还有助于有效地使用窗口的客户区。

16 QSplitter

这是另一个高级布局管理器,它允许通过拖动子部件之间的边界来动态更改子部件的大小。Splitter 控件提供了一个手柄,可以拖动该手柄来调整控件的大小。

17 号 QDock

可停靠窗口是可以保持浮动状态或可以附加到主窗口指定位置的子窗口。QMainWindow 类的主窗口对象有一个为可停靠窗口保留的区域。

18 Q状态栏

QMainWindow对象在底部保留一个水平条作为状态栏。它用于显示永久或上下文状态信息。

19 问题列表

QListWidget 类是一个基于项目的接口,用于从列表中添加或删除项目。列表中的每个项目都是一个 QListWidgetItem 对象。ListWidget 可以设置为多选。

20 Q滚动条

滚动条控件使用户能够访问文档中可视区域之外的部分。它提供当前位置的视觉指示器。

21 QC日历

QCalendar 小部件是一个有用的日期选择器控件。它提供了基于月份的视图。用户可以通过使用鼠标或键盘来选择日期,默认为今天的日期。

PyQt5 - QDialog 类

QDialog小部件提供了一个顶级窗口,主要用于收集用户的响应。它可以配置为模态(阻止其父窗口)或无模式(可以绕过对话框窗口)。

PyQt API 有许多预配置的对话框小部件,例如 InputDialog、FileDialog、FontDialog 等。

例子

在下面的示例中, Dialog 窗口的WindowModality属性决定它是模态还是非模态。对话框上的任何一个按钮都可以设置为默认按钮。当用户按下 Escape 键时,QDialog.reject()方法将丢弃该对话框。

单击顶级 QWidget 窗口上的按钮时,会生成一个对话框窗口。对话框的标题栏上没有最小化和最大化控件。

用户无法将此对话框降级到后台,因为其 WindowModality 设置为ApplicationModal

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   w = QWidget()
   btn = QPushButton(w)
   btn.setText("Hello World!")
   btn.move(100,50)
   btn.clicked.connect(showdialog)
   w.setWindowTitle("PyQt Dialog demo")
   w.show()
   sys.exit(app.exec_())

def showdialog():
   dlg = QDialog()
   b1 = QPushButton("ok",dlg)
   b1.move(50,50)
   dlg.setWindowTitle("Dialog") 9. PyQt5 — QDialog Class
   dlg.setWindowModality(Qt.ApplicationModal)
   dlg.exec_()

if __name__ == '__main__':
   window()

上面的代码产生以下输出。单击主窗口中的按钮,弹出对话框 -

QDialog 类输出

PyQt5 - QMessageBox

QMessageBox是一种常用的模式对话框,用于显示一些信息性消息,并可选择要求用户通过单击其上的任何一个标准按钮进行响应。每个标准按钮都有一个预定义的标题、一个角色并返回一个预定义的十六进制数字。

下表给出了与 QMessageBox 类相关的重要方法和枚举 -

先生。 方法与说明
1

设置图标()

显示与消息严重性相对应的预定义图标

  • 问题
  • 信息
  • 警告
  • 批判的
2

设置文本()

设置要显示的主要消息的文本

3

设置信息文本()

显示附加信息

4

设置详细信息文本()

对话框显示“详细信息”按钮。单击该文本后会出现该文本

5

设置标题()

显示对话框的自定义标题

6

设置标准按钮()

要显示的标准按钮列表。每个按钮都与

QMessageBox.确定0x00000400

QMessageBox.打开0x00002000

QMessageBox.保存0x00000800

QMessageBox.取消0x00400000

QMessageBox.关闭0x00200000

QMessageBox.是0x00004000

QMessageBox.No 0x00010000

QMessageBox.中止0x00040000

QMessageBox.重试0x00080000

QMessageBox.忽略0x00100000

7

设置默认按钮()

将按钮设置为默认值。如果按下 Enter 键,它会发出单击信号

8

设置退出按钮()

如果按下退出键,则将按钮设置为单击

例子

在下面的示例中,单击顶层窗口上的按钮信号,连接的函数将显示消息框对话框。

msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText("This is a message box")
msg.setInformativeText("This is additional information")
msg.setWindowTitle("MessageBox demo")
msg.setDetailedText("The details are as follows:")

setStandardButton() 函数显示所需的按钮。

msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)

ButtonClicked() 信号连接到一个槽函数,该函数标识信号源的标题。

msg.buttonClicked.connect(msgbtn)

该示例的完整代码如下 -

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   w = QWidget()
   b = QPushButton(w)
   b.setText("Show message!")
   
   b.move(100,50)
   b.clicked.connect(showdialog)
   w.setWindowTitle("PyQt MessageBox demo")
   w.show()
   sys.exit(app.exec_())

def showdialog():
   msg = QMessageBox()
   msg.setIcon(QMessageBox.Information)
   
   msg.setText("This is a message box")
   msg.setInformativeText("This is additional information")
   msg.setWindowTitle("MessageBox demo")
   msg.setDetailedText("The details are as follows:")
   msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
   msg.buttonClicked.connect(msgbtn)

   retval = msg.exec_()

def msgbtn(i):
   print ("Button pressed is:",i.text())

if __name__ == '__main__':
   window()

上面的代码产生以下输出。单击主窗口按钮时会弹出消息框 -

QMessageBox输出

如果单击 MessageBox 上的“确定”或“取消”按钮,控制台上会生成以下输出 -

Button pressed is: OK
Button pressed is: Cancel

PyQt5 - 多文档界面

典型的 GUI 应用程序可能有多个窗口。选项卡式和堆叠式小部件允许一次激活一个这样的窗口。然而,很多时候这种方法可能没有用,因为其他窗口的视图被隐藏了。

同时显示多个窗口的一种方法是将它们创建为独立的窗口。这称为 SDI (单文档接口)。这需要更多的内存资源,因为每个窗口可能有自己的菜单系统、工具栏等。

MDI (多文档界面)应用程序消耗更少的内存资源。子窗口相对于彼此放置在主容器内。容器小部件称为QMdiArea

QMdiArea小部件通常占据QMainWondow对象的中央小部件。该区域中的子窗口是QMdiSubWindow类的实例。可以将任何 QWidget 设置为 subWindow 对象的内部小部件。MDI 区域中的子窗口可以按级联或平铺方式排列。

下表列出了 QMdiArea 类和 QMdiSubWindow 类的重要方法 -

先生。 方法与说明
1

添加子窗口()

在 MDI 区域中添加一个小部件作为新的子窗口

2

移除子窗口()

删除属于子窗口内部小部件的小部件

3

设置活动子窗口()

激活子窗口

4

级联子窗口()

以级联方式排列 MDiArea 中的子窗口

5

瓦片子窗口()

以平铺方式排列 MDiArea 中的子窗口

6

关闭活动子窗口()

关闭活动子窗口

7

子窗口列表()

返回MDI区域中的子窗口列表

8

设置小部件()

将 QWidget 设置为 QMdiSubwindow 实例的内部小部件

QMdiArea 对象发出 subWindowActivated() 信号,而 windowStateChanged() 信号由 QMdisubWindow 对象发出。

例子

在下面的示例中,由 QMainWindow 组成的顶级窗口具有菜单和 MdiArea。

self.mdi = QMdiArea()
self.setCentralWidget(self.mdi)
bar = self.menuBar()
file = bar.addMenu("File")

file.addAction("New")
file.addAction("cascade")
file.addAction("Tiled")

菜单的 Triggered() 信号连接到 windowaction() 函数。

file.triggered[QAction].connect(self.windowaction)

菜单的新操作在 MDI 区域中添加了一个子窗口,其标题具有增量编号。

MainWindow.count = MainWindow.count+1
sub = QMdiSubWindow()
sub.setWidget(QTextEdit())
sub.setWindowTitle("subwindow"+str(MainWindow.count))
self.mdi.addSubWindow(sub)
sub.show()

菜单的级联和平铺按钮分别以级联和平铺方式排列当前显示的子窗口。

完整代码如下 -

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class MainWindow(QMainWindow):
   count = 0

   def __init__(self, parent = None):
      super(MainWindow, self).__init__(parent)
      self.mdi = QMdiArea()
      self.setCentralWidget(self.mdi)
      bar = self.menuBar()

      file = bar.addMenu("File")
      file.addAction("New")
      file.addAction("cascade")
      file.addAction("Tiled")
      file.triggered[QAction].connect(self.windowaction)
      self.setWindowTitle("MDI demo")

   def windowaction(self, q):
      print ("triggered")
   
      if q.text() == "New":
         MainWindow.count = MainWindow.count+1
         sub = QMdiSubWindow()
         sub.setWidget(QTextEdit())
         sub.setWindowTitle("subwindow"+str(MainWindow.count))
         self.mdi.addSubWindow(sub)
         sub.show()

      if q.text() == "cascade":
         self.mdi.cascadeSubWindows()

      if q.text() == "Tiled":
         self.mdi.tileSubWindows()

def main():
   app = QApplication(sys.argv)
   ex = MainWindow()
   ex.show()
   sys.exit(app.exec_())

if __name__ == '__main__':
   main()

运行上面的代码和三个层叠和平铺的窗口 -

多文档接口输出1

多文档接口输出2

多文档接口输出3

PyQt5 - 拖放

拖放功能对于用户来说非常直观。它存在于许多桌面应用程序中,用户可以将对象从一个窗口复制或移动到另一个窗口。

基于 MIME 的拖放数据传输基于QDrag类。QMimeData对象将数据与其相应的 MIME 类型相关联。它存储在剪贴板上,然后在拖放过程中使用。

下面的QMimeData类函数可以方便地检测和使用MIME类型。

测试员 吸气剂 塞特 MIME 类型
有文本() 文本() 设置文本() 文本/纯文本
hasHtml() html() 设置Html() 文本/html
hasUrls() 网址() 设置网址() 文本/uri-列表
有图像() 图像数据() 设置图像数据() 图像/ *
有颜色() 颜色数据() 设置颜色数据() 应用程序/x-颜色

许多 QWidget 对象支持拖放活动。那些允许拖动数据的 setDragEnabled() 必须设置为 true。另一方面,小部件应该响应拖放事件,以便存储拖入其中的数据。

  • DragEnterEvent提供了一个事件,当拖动操作进入目标窗口小部件时,该事件会发送到目标窗口小部件。

  • DragMoveEvent在拖放操作正在进行时使用。

  • 当拖放操作离开小部件时,会生成DragLeaveEvent 。

  • 另一方面,DropEvent在放置完成时发生。事件提议的行动可以有条件地接受或拒绝。

例子

在以下代码中,DragEnterEvent验证事件的 MIME 数据是否包含文本。如果是,则接受事件建议的操作,并将文本作为新项目添加到组合框中。

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class combo(QComboBox):
   def __init__(self, title, parent):
      super(combo, self).__init__( parent)
      self.setAcceptDrops(True)

   def dragEnterEvent(self, e):
      print (e)

      if e.mimeData().hasText():
         e.accept()
      else:
         e.ignore()

   def dropEvent(self, e):
      self.addItem(e.mimeData().text())

class Example(QWidget):
   def __init__(self):
      super(Example, self).__init__()

      self.initUI()

   def initUI(self):
      lo = QFormLayout()
      lo.addRow(QLabel("Type some text in textbox and drag it into combo box"))
   
      edit = QLineEdit()
      edit.setDragEnabled(True)
      com = combo("Button", self)
      lo.addRow(edit,com)
      self.setLayout(lo)
      self.setWindowTitle('Simple drag and drop')
def main():
   app = QApplication(sys.argv)
   ex = Example()
   ex.show()
   app.exec_()

if __name__ == '__main__':
   main()

上面的代码产生以下输出 -

拖放输出

PyQt5 - 数据库处理

PyQt5 库包含QtSql模块。它是一个精心设计的类系统,可以与许多基于 SQL 的数据库进行通信。它的QSqlDatabase通过 Connection 对象提供访问。以下是当前可用的 SQL 驱动程序的列表 -

先生。 驱动程序类型和描述
1

QDB2

IBM DB2

2

启基数据库

Borland InterBase 驱动程序

3

QMYSQL

MySQL驱动程序

4

QOCI

Oracle 调用接口驱动程序

5

QODBC

ODBC 驱动程序(包括 Microsoft SQL Server)

6

QPSQL

PostgreSQL 驱动程序

7

QSQLITE

SQLite 版本 3 或更高版本

8

QSQLITE2

SQLite 版本 2

例子

在本章中,使用静态方法建立与 SQLite 数据库的连接 -

db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('sports.db')

QSqlDatabase 类的其他方法如下 -

先生。 方法与说明
1

设置数据库名称()

设置寻求连接的数据库的名称

2

设置主机名()

设置安装数据库的主机的名称

3

设置用户名()

指定连接的用户名

4

设置密码()

设置连接对象的密码(如果有)

5

犯罪()

提交交易,如果成功则返回 true

6

回滚()

回滚数据库事务

7

关闭()

关闭连接

QSqlQuery类具有执行和操作 SQL 命令的功能。可以执行DDL 和DML 类型的SQL 查询。第一步是使用以下语句创建 SQlite 数据库 -

db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('sportsdatabase.db')

接下来,使用QSqlQuery()方法获取 Query 对象,并调用其最重要的方法 exec_(),该方法将包含要执行的 SQL 语句的字符串作为参数。

query = QtSql.QSqlQuery()
query.exec_("create table sportsmen(id int primary key, " "firstname varchar(20), lastname varchar(20))")

以下脚本创建一个 SQLite 数据库 sports.db,其中包含一个填充有 5 条记录的运动员表。

import sys
from PyQt5.QtSql import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def createDB():
   db = QSqlDatabase.addDatabase('QSQLITE')
   db.setDatabaseName('sportsdatabase.db')

   if not db.open():
      msg = QMessageBox()
      msg.setIcon(QMessageBox.Critical)
      msg.setText("Error in Database Creation")
      retval = msg.exec_()
      return False
   query = QSqlQuery()

   query.exec_("create table sportsmen(
      id int primary key, ""firstname varchar(20), lastname varchar(20))")

   query.exec_("insert into sportsmen values(101, 'Roger', 'Federer')")
   query.exec_("insert into sportsmen values(102, 'Christiano', 'Ronaldo')")
   query.exec_("insert into sportsmen values(103, 'Ussain', 'Bolt')")
   query.exec_("insert into sportsmen values(104, 'Sachin', 'Tendulkar')")
   query.exec_("insert into sportsmen values(105, 'Saina', 'Nehwal')")
   return True

if __name__ == '__main__':
   app = QApplication(sys.argv)
   createDB()

要确认 SQLite 数据库是使用在 sportsmen 表中添加的上述记录创建的,请使用名为SQLiteStudio的 SQLite Gui 实用程序。

数据库处理

PyQt 中的QSqlTableModel类是一个高级接口,它提供可编辑的数据模型,用于在单个表中读取和写入记录。该模型用于填充QTableView对象。它向用户呈现一个可滚动且可编辑的视图,可以放置在任何顶级窗口上。

QSqlTableModel 对象按以下方式声明 -

model = QtSql.QSqlTableModel()

其编辑策略可以设置为以下任意一项 -

QSqlTableModel.OnFieldChange 所有更改将立即应用
QSqlTableModel.OnRowChange 当用户选择不同的行时将应用更改
QSqlTableModel.OnManualSubmit 所有更改都将被缓存,直到调用 SubmitAll() 或 revertAll()

例子

在以下示例中,使用运动员表作为模型,策略设置为 -

model.setTable('sportsmen') 
model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
   model.select()

QTableView 类是 PyQt 中模型/视图框架的一部分。QTableView 对象的创建如下 -

view = QtGui.QTableView()
view.setModel(model)
view.setWindowTitle(title)
return view

这个 QTableView 对象和两个 QPushButton 小部件被添加到顶级 QDialog 窗口中。添加按钮的 Clicked() 信号连接到 addrow(),后者在模型表上执行 insertRow()。

button.clicked.connect(addrow)
def addrow():
   print model.rowCount()
   ret = model.insertRows(model.rowCount(), 1)
   print ret

与删除按钮关联的槽执行 lambda 函数,删除用户选择的行。

btn1.clicked.connect(lambda: model.removeRow(view1.currentIndex().row()))

完整代码如下 -

import sys
from PyQt5.QtSql import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def initializeModel(model):
   model.setTable('sportsmen')
   model.setEditStrategy(QSqlTableModel.OnFieldChange)
   model.select()
   model.setHeaderData(0, Qt.Horizontal, "ID")
   model.setHeaderData(1, Qt.Horizontal, "First name")
   model.setHeaderData(2, Qt.Horizontal, "Last name")

def createView(title, model):
   view = QTableView()
   view.setModel(model)
   view.setWindowTitle(title)
   return view

def addrow():
   print (model.rowCount())
   ret = model.insertRows(model.rowCount(), 1)
   print (ret)

def findrow(i):
   delrow = i.row()

if __name__ == '__main__':
   app = QApplication(sys.argv)
   db = QSqlDatabase.addDatabase('QSQLITE')
   db.setDatabaseName('sportsdatabase.db')
   model = QSqlTableModel()
   delrow = -1
   initializeModel(model)

   view1 = createView("Table Model (View 1)", model)
   view1.clicked.connect(findrow)

   dlg = QDialog()
   layout = QVBoxLayout()
   layout.addWidget(view1)

   button = QPushButton("Add a row")
   button.clicked.connect(addrow)
   layout.addWidget(button)

   btn1 = QPushButton("del a row")
   btn1.clicked.connect(lambda: model.removeRow(view1.currentIndex().row()))
   layout.addWidget(btn1)

   dlg.setLayout(layout)
   dlg.setWindowTitle("Database Demo")
   dlg.show()
   sys.exit(app.exec_())

上面的代码产生以下输出 -

数据库处理输出

尝试添加和删除一些记录,然后返回 SQLiteStudio 确认事务。

PyQt5 - 绘图 API

PyQt 中的所有QWidget类都是 QPaintDevice 类的子类。QPaintDevice是二维空间的抽象,可以使用 QPainter 进行绘制绘画设备的尺寸从左上角开始以像素为单位进行测量。

QPainter类在小部件和其他可绘制设备(例如打印机)上执行低级绘制。通常,它用在小部件的绘制事件中。每当窗口部件的外观更新时,QPaintEvent就会发生。

画家通过调用begin()方法来激活,而end()方法则将其停用。其间,通过下表中列出的适当方法绘制所需的图案。

先生。 方法与说明
1

开始()

开始在目标设备上绘画

2

绘制弧线()

在起始角度和结束角度之间绘制圆弧

3

画椭圆()

在矩形内绘制椭圆

4

画线()

绘制一条指定端点坐标的线

5

绘制像素图()

从图像文件中提取pixmap并将其显示在指定位置

6

drwaPolygon()

使用坐标数组绘制多边形

7

绘制矩形()

从左上角坐标开始绘制一个具有给定宽度和高度的矩形

8

绘制文本()

在给定坐标处显示文本

9

填充矩形()

使用 QColor 参数填充矩形

10

设置画笔()

设置绘画的画笔样式

11

设置笔()

设置用于绘图的笔的颜色、大小和样式

例子

在下面的代码中,使用了PyQt的绘图方法的各种方法。

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class Example(QWidget):
   def __init__(self):
      super(Example, self).__init__()
      self.initUI()

   def initUI(self):
      self.text = "hello world"
      self.setGeometry(100,100, 400,300)
      self.setWindowTitle('Draw Demo')
      self.show()

   def paintEvent(self, event):
      qp = QPainter()
      qp.begin(self)
      qp.setPen(QColor(Qt.red))
      qp.setFont(QFont('Arial', 20))
      qp.drawText(10,50, "hello Python")
      qp.setPen(QColor(Qt.blue))
      qp.drawLine(10,100,100,100)
      qp.drawRect(10,150,150,100)
      qp.setPen(QColor(Qt.yellow))
      qp.drawEllipse(100,50,100,50)
      qp.drawPixmap(220,10,QPixmap("pythonlogo.png"))
      qp.fillRect(20,175,130,70,QBrush(Qt.SolidPattern))
      qp.end()

def main():
   app = QApplication(sys.argv)
   ex = Example()
   sys.exit(app.exec_())

if __name__ == '__main__':
   main()

上面的代码产生以下输出 -

数据库处理输出

PyQt5 - BrushStyle 常量

在本章中,我们将学习画笔样式常量。

画笔样式常量

下面给出的是画笔样式常量 -

Qt.NoBrush 无画笔图案
Qt.SolidPattern 颜色均匀
Qt.Dense1Pattern 极其密集的笔刷图案
Qt.HorPattern 水平线
Qt.VerPattern 垂直线
Qt.CrossPattern 跨越水平线和垂直线
Qt.BDiagPattern 向后对角线
Qt.FDiagPattern 向前对角线
Qt.DiagCrossPattern 穿过对角线

预定义的 QColor 样式

下面给出的是预定义的 QColor 样式 -

Qt.NoBrush 无画笔图案
Qt.SolidPattern 颜色均匀
Qt.Dense1Pattern 极其密集的笔刷图案
Qt.HorPattern 水平线
Qt.VerPattern 垂直线
Qt.CrossPattern 跨越水平线和垂直线
Qt.BDiagPattern 向后对角线
Qt.FDiagPattern 向前对角线
Qt.DiagCrossPattern 穿过对角线

预定义的 QColor 对象

下面给出的是预定义的 QColor 对象 -

怀特Qt
Qt.black
红Qt
Qt.深红
Qt绿色
Qt.深绿
Qt.蓝
青色Qt
洋红Qt
黄Qt
Qt.暗黄
Qt.格雷

PyQt5 - QClipboard

QClipboard类提供对系统范围剪贴板的访问,该剪贴板提供了在应用程序之间复制和粘贴数据的简单机制它的操作与QDrag类类似,并且使用类似的数据类型。

QApplication类有一个静态方法clipboard(),它返回对剪贴板对象的引用。任何类型的 MimeData 都可以复制到剪贴板或从剪贴板粘贴。

以下是常用的剪贴板类方法 -

先生。 方法与说明
1

清除()

清除剪贴板内容

2

设置图像()

将 QImage 复制到剪贴板

3

设置MimeData()

将 MIME 数据设置到剪贴板

4

设置像素图()

复制剪贴板中的 Pixmap 对象

5

设置文本()

复制剪贴板中的 QString

6

文本()

从剪贴板检索文本

与剪贴板对象关联的信号是 -

先生。 方法及说明
1

数据改变()

每当剪贴板数据发生变化时

例子

在以下示例中,两个 TextEdit 对象和两个按钮被添加到顶级窗口。

首先实例化剪贴板对象。textedit 对象的 Copy() 方法将数据复制到系统剪贴板。单击“粘贴”按钮时,它会获取剪贴板数据并将其粘贴到其他文本编辑对象中。

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class Example(QWidget):
   def __init__(self):
      super(Example, self).__init__()

      self.initUI()

   def initUI(self):
      hbox = QVBoxLayout()
      self.edit1=QTextEdit()
      hbox.addWidget(self.edit1)
      self.btn1=QPushButton("Copy")
      hbox.addWidget(self.btn1)
      self.edit2=QTextEdit()
      self.btn2=QPushButton("Paste")
      hbox.addWidget(self.edit2)
      hbox.addWidget(self.btn2)
      self.btn1.clicked.connect(self.copytext)
      self.btn2.clicked.connect(self.pastetext)
      self.setLayout(hbox)
      
      self.setGeometry(300, 300, 300, 200)
      self.setWindowTitle('Clipboard')
      self.show()
      
   def copytext(self):

      #clipboard.setText(self.edit1.copy())
      self.edit1.copy()
      print (clipboard.text())

      msg=QMessageBox()
      msg.setText(clipboard.text()+" copied on clipboard")
      msg.exec_()

   def pastetext(self):
      self.edit2.setText(clipboard.text())

app = QApplication(sys.argv)
clipboard=app.clipboard()
ex = Example()
ex.setWindowTitle("clipboard Example")
sys.exit(app.exec_())

上面的代码产生以下输出 -

QC剪贴板

PyQt5 - QPixmap 类

QPixmap类提供图像的离屏表示。它可以用作 QPaintDevice 对象,也可以加载到另一个小部件中,通常是标签或按钮。

Qt API 有另一个类似的类QImage,它针对 I/O 和其他像素操作进行了优化。另一方面,像素图针对在屏幕上显示进行了优化。两种格式可以相互转换。

可以读入 QPixmap 对象的图像文件类型如下 -

骨形态发生蛋白 窗口位图
动图 图形交换格式(可选)
JPG 联合摄影专家组
JPEG 联合摄影专家组
巴布亚新几内亚 便携式网络图形
药物管理 便携式位图
铂族金属 便携式灰度图
生产计划管理 便携式像素图
XBM X11 位图
XPM X11 像素图

以下方法在处理 QPixmap 对象时很有用 -

先生。 方法与说明
1

复制()

从 QRect 对象复制像素图数据

2

从图像()

将 QImage 对象转换为 QPixmap

3

抓取Widget()

从给定的小部件创建像素图

4

抓取窗口()

在窗口中创建数据的像素图

5

加载()

将图像文件加载为像素图

6

节省()

将 QPixmap 对象保存为文件

7

印象

将 QPixmap 转换为 Q