PyQt 快速指南



PyQt - 简介

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

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

支持的环境

PyQt 兼容所有流行的操作系统,包括 Windows、Linux 和 Mac OS。它采用双重许可,可在 GPL 和商业许可下使用。

Windows

您可以从上面的下载链接下载并安装相应的安装程序,该安装程序对应于 Python 版本 (2.7 或 3.4) 和硬件架构 (32 位或 64 位)。请注意,PyQt 有两个版本可用,即 **PyQt 4.8** 和 **PyQt 5.5**。

PyQt4 可用于 Python 2 和 Python 3,而 PyQt5 只能与 Python 3.* 一起使用。

PyQt4 Windows 二进制文件

PyQt4-4.11.4-gpl-Py3.4-Qt4.8.7-x64.exe Windows 64 位安装程序
PyQt4-4.11.4-gpl-Py3.4-Qt4.8.7-x32.exe Windows 32 位安装程序
PyQt4-4.11.4-gpl-Py3.4-Qt5.5.0-x64.exe Windows 64 位安装程序
PyQt4-4.11.4-gpl-Py3.4-Qt5.5.0-x32.exe Windows 32 位安装程序
PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x64.exe Windows 64 位安装程序
PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x32.exe Windows 32 位安装程序

PyQt5 Windows 二进制文件

PyQt5-5.5-gpl-Py3.4-Qt5.5.0-x64.exe Windows 64 位安装程序
PyQt5-5.5-gpl-Py3.4-Qt5.5.0-x32.exe Windows 32 位安装程序

Linux

对于 Ubuntu 或任何其他 Debian Linux 发行版,使用以下命令安装 PyQt:

sudo apt-get install python-qt4
or 
sudo apt-get install pyqt5-dev-tools

您也可以从“下载”页面提供的源代码进行构建。

PyQt-x11-gpl-4.11.4.tar.gz Linux、UNIX PyQt4 源代码
PyQt-gpl-5.5.tar.gz Linux、UNIX、MacOS/X PyQt5 源代码

Mac OS

PyQtX 项目 (http://sourceforge.net/projects/pyqtx/) 托管 PyQt 的 Mac 二进制文件。使用 Homebrew 安装程序,按照以下命令:

brew install pyqt

PyQt - Hello World

使用 PyQt 创建简单的 GUI 应用程序包含以下步骤:

  • 导入 QtGui 模块。

  • 创建一个应用程序对象。

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

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

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

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

import sys
from PyQt4 import QtGui

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

以上代码产生以下输出:

Hello World

PyQt - 主要类

**PyQt API** 是一个大型的类和方法集合。这些类在 20 多个模块中定义。以下是经常使用的一些模块:

序号 模块和描述
1

QtCore

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

2

QtGui

图形用户界面组件

3

QtMultimedia

用于低级多媒体编程的类

4

QtNetwork

用于网络编程的类

5

QtOpenGL

OpenGL 支持类

6

QtScript

用于评估 Qt 脚本的类

7

QtSql

使用 SQL 集成数据库的类

8

QtSvg

用于显示 SVG 文件内容的类

9

QtWebKit

用于渲染和编辑 HTML 的类

10

QtXml

用于处理 XML 的类

11

QtAssistant

在线帮助支持

12

QtDesigner

用于扩展 Qt Designer 的类

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

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

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

下图描述了它们层次结构中的一些重要类。

Hierarchy QWidget QDialog QIODevice QPaintDevice

这是一个经常使用的控件的选择列表:

以下是常用控件。

序号 控件和描述
1

QLabel

用于显示文本或图像

2

QLineEdit

允许用户输入一行文本

3

QTextEdit

允许用户输入多行文本

4

QPushButton

一个命令按钮来调用操作

5

QRadioButton

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

6

QCheckBox

允许选择多个选项

7

QSpinBox

允许增加/减少整数值

8

QScrollBar

允许访问超出显示区域的控件内容

9

QSlider

允许线性更改绑定值。

10

QComboBox

提供一个下拉列表供选择

11

QMenuBar

包含 QMenu 对象的水平条

12

QStatusBar

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

13

QToolBar

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

14

QListView

以列表模式或图标模式提供可选择的项目列表

15

QPixmap

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

16

QDialog

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

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

下图显示了 QMainWindow 框架:

QMainWindow

PyQt - 使用 Qt Designer

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

使用 Qt Designer 创建 GUI 界面首先要为应用程序选择一个顶级窗口。

Qt Designer1

然后,您可以将所需的控件从左侧窗格的控件框中拖放到表单上。您还可以为表单上控件的属性赋值。

Qt Designer2

设计的表单将保存为 demo.ui。此 ui 文件包含设计中控件及其属性的 XML 表示。此设计通过使用 pyuic4 命令行实用程序转换为 Python 等效项。此实用程序是 uic 模块的包装器。pyuic4 的用法如下:

pyuic4 –x demo.ui –o demo.py

在上述命令中,-x 开关会向生成的 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 脚本将显示以下对话框:

Dialog Box

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

PyQt - 信号与槽

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

用于构建 GUI 界面的控件充当此类事件的来源。每个从 QObject 类派生的 PyQt 控件都设计为响应一个或多个事件而发出“**信号**”。信号本身不会执行任何操作。相反,它连接到“**槽**”。槽可以是任何 **可调用的 Python 函数**。

在 PyQt 中,信号和槽之间的连接可以通过不同的方式实现。以下是最常用的技术:

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

当控件发出信号时,调用 slot_function 的更方便的方法如下:

widget.signal.connect(slot_function)

假设需要在单击按钮时调用一个函数。这里,单击信号需要连接到一个可调用的函数。这可以通过以下两种技术中的任何一种实现:

QtCore.QObject.connect(button, QtCore.SIGNAL(“clicked()”), 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() 函数

QObject.connect(b2, SIGNAL("clicked()"), b2_clicked)

示例

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui 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)
   QObject.connect(b2,SIGNAL("clicked()"),b2_clicked)

   win.setGeometry(100,100,200,100)
   win.setWindowTitle("PyQt")
   win.show()
   sys.exit(app.exec_())

def b1_clicked():
   print "Button 1 clicked"

def b2_clicked():
   print "Button 2 clicked"

if __name__ == '__main__':
   window()

以上代码产生以下输出:

Signals and Slots Output

输出

Button 1 clicked
Button 2 clicked

PyQt - 布局管理

可以通过指定其以像素为单位测量的绝对坐标,将 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 像素的位置。

然而,这种 **绝对定位** 由于以下原因并不适用:

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

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

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

Original and Resized Window

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

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

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

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

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

序号 类与说明
1 QBoxLayout

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

2 QGridLayout

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

3 QFormLayout

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

PyQt - 基本控件

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

序号 控件和描述
1 QLabel

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

2 QLineEdit

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

3 QPushButton

在 PyQt API 中,QPushButton 类对象显示一个按钮,单击该按钮可以编程为调用某个函数。

4 QRadioButton

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

5 QCheckBox

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

6 QComboBox

QComboBox 对象显示一个下拉列表,从中选择项目。它在表单上占据最小的屏幕空间,只需显示当前选定的项目。

7 QSpinBox

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

8 QSlider 小部件和信号

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

9 QMenuBar、QMenu 和 QAction

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

10 QToolBar

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

11 QInputDialog

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

12 QFontDialog

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

13 QFileDialog

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

14 QTab

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

15 QStacked

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

16 QSplitter

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

17 QDock

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

18 QStatusBar

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

19 QList

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

20 QScrollBar

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

21 QCalendar

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

PyQt - QDialog 类

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

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

示例

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

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

用户无法将此对话框框置于后台,因为其 WindowModality 设置为 ApplicationModal。

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

def window():
   app = QApplication(sys.argv)
   w = QWidget()
   b = QPushButton(w)
   b.setText("Hello World!")
   b.move(50,50)
   b.clicked.connect(showdialog)
   w.setWindowTitle("PyQt Dialog demo")
   w.show()
   sys.exit(app.exec_())
	
def showdialog():
   d = QDialog()
   b1 = QPushButton("ok",d)
   b1.move(50,50)
   d.setWindowTitle("Dialog")
   d.setWindowModality(Qt.ApplicationModal)
   d.exec_()
	
if __name__ == '__main__':
   window()

以上代码产生以下输出:

QDialog Class Output

PyQt - QMessageBox

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

与 QMessageBox 类关联的重要方法和枚举在下面的表格中给出:

序号 方法与说明
1

setIcon()

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

Question 疑问

Information 信息

Warning 警告

Critical 严重错误

2

setText()

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

3

setInformativeText()

显示附加信息

4

setDetailText()

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

5

setTitle()

显示对话框的自定义标题

6

setStandardButtons()

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

QMessageBox.Ok 0x00000400

QMessageBox.Open 0x00002000

QMessageBox.Save 0x00000800

QMessageBox.Cancel 0x00400000

QMessageBox.Close 0x00200000

QMessageBox.Yes 0x00004000

QMessageBox.No 0x00010000

QMessageBox.Abort 0x00040000

QMessageBox.Retry 0x00080000

QMessageBox.Ignore 0x00100000

7

setDefaultButton()

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

8

setEscapeButton()

将按钮设置为在按下 Escape 键时视为已单击

示例

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

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 PyQt4.QtGui import *
from PyQt4.QtCore import *

def window():
   app = QApplication(sys.argv)
   w = QWidget()
   b = QPushButton(w)
   b.setText("Show message!")

   b.move(50,50)
   b.clicked.connect(showdialog)
   w.setWindowTitle("PyQt Dialog 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_()
   print "value of pressed message box button:", retval
	
def msgbtn(i):
   print "Button pressed is:",i.text()
	
if __name__ == '__main__': 
   window()

以上代码产生以下输出:

QMessageBox Output1 QMessageBox Output2

PyQt - 多文档界面

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

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

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

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

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

序号 方法与说明
1

addSubWindow()

将小部件作为新子窗口添加到 MDI 区域

2

removeSubWindow()

删除作为子窗口内部小部件的小部件

3

setActiveSubWindow()

激活子窗口

4

cascadeSubWindows()

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

5

tileSubWindows()

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

6

closeActiveSubWindow()

关闭活动子窗口

7

subWindowList()

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

8

setWidget()

将一个 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 PyQt4.QtCore import *
from PyQt4.QtGui 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()

以上代码产生以下输出:

Multiple Document Interface Output1 Multiple Document Interface Output2 Multiple Document Interface Output3

PyQt - 拖放

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

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

以下 QMimeData 类函数允许方便地检测和使用 MIME 类型。

测试器 获取器 设置器 MIME 类型
hasText() text() setText() text/plain
hasHtml() html() setHtml() text/html
hasUrls() urls() setUrls() text/uri-list
hasImage() imageData() setImageData() image/*
hasColor() colorData() setColorData() application/x-color

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

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

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

  • DragLeaveEvent 在拖放操作离开窗口部件时生成。

  • 另一方面,DropEvent 在放下操作完成后发生。可以有条件地接受或拒绝事件的建议操作。

示例

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

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore 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 & drop')
		
def main():
   app = QApplication(sys.argv)
   ex = Example()
   ex.show()
   app.exec_()
	
if __name__ == '__main__':
   main()

以上代码产生以下输出:

Drag and Drop Output

PyQt - 数据库操作

PyQt API 包含一个详尽的类系统,用于与许多基于 SQL 的数据库进行通信。它的 QSqlDatabase 通过 Connection 对象提供访问。以下是当前可用的 SQL 驱动程序列表:

序号 驱动程序类型和描述
1

QDB2

IBM DB2

2

QIBASE

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

setDatabaseName()

设置要与其建立连接的数据库的名称

2

setHostName()

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

3

setUserName()

指定连接的用户名

4

setPassword()

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

5

commit()

提交事务,如果成功则返回 true

6

rollback()

回滚数据库事务

7

close()

关闭连接

QSqlQuery 类具有执行和操作 SQL 命令的功能。可以执行 DDL 和 DML 类型的 SQL 查询。该类中最重要的函数是 exec_(),它接受一个包含要执行的 SQL 语句的字符串作为参数。

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

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

from PyQt4 import QtSql, QtGui

def createDB():
   db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
   db.setDatabaseName('sports.db')
	
   if not db.open():
      QtGui.QMessageBox.critical(None, QtGui.qApp.tr("Cannot open database"),
         QtGui.qApp.tr("Unable to establish a database connection.\n"
            "This example needs SQLite support. Please read "
            "the Qt SQL driver documentation for information "
            "how to build it.\n\n" "Click Cancel to exit."),
         QtGui.QMessageBox.Cancel)
			
      return False
		
   query = QtSql.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__':
   import sys
	
   app = QtGui.QApplication(sys.argv)
   createDB()

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

QTableModel 对象的声明方式如下:

model = QtSql.QSqlTableModel()

其编辑策略可以设置为以下任何一种:

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

示例

在以下示例中,sportsperson 表用作模型,策略设置为:

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

   model.select()

QTableView 类是 PyQt 中 Model/View 框架的一部分。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 PyQt4 import QtCore, QtGui, QtSql
import sportsconnection

def initializeModel(model):
   model.setTable('sportsmen')
   model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
   model.select()
   model.setHeaderData(0, QtCore.Qt.Horizontal, "ID")
   model.setHeaderData(1, QtCore.Qt.Horizontal, "First name")
   model.setHeaderData(2, QtCore.Qt.Horizontal, "Last name")
	
def createView(title, model):
   view = QtGui.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 = QtGui.QApplication(sys.argv)
   db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
   db.setDatabaseName('sports.db')
   model = QtSql.QSqlTableModel()
   delrow = -1
   initializeModel(model)
	
   view1 = createView("Table Model (View 1)", model)
   view1.clicked.connect(findrow)
	
   dlg = QtGui.QDialog()
   layout = QtGui.QVBoxLayout()
   layout.addWidget(view1)
	
   button = QtGui.QPushButton("Add a row")
   button.clicked.connect(addrow)
   layout.addWidget(button)
	
   btn1 = QtGui.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_())

以上代码产生以下输出:

Database Handling Output

PyQt - 绘图 API

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

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

通过调用 begin() 方法激活画家,而 end() 方法停用它。在这两者之间,通过以下表格中列出的合适方法绘制所需的图案。

序号 方法与说明
1

begin()

开始在目标设备上绘制

2

drawArc()

绘制起始角度和结束角度之间的弧线

3

drawEllipse()

在矩形内绘制椭圆

4

drawLine()

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

5

drawPixmap()

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

6

drawPolygon()

使用坐标数组绘制多边形

7

drawRect()

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

8

drawText()

在给定坐标处显示文本

9

fillRect()

用 QColor 参数填充矩形

10

setBrush()

设置绘图的画笔样式

11

setPen()

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

PyQt - BrushStyle 常量

预定义的 QColor 样式

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

预定义的 QColor 对象

Qt.white
Qt.black
Qt.red
Qt.darkRed
Qt.green
Qt.darkGreen
Qt.blue
Qt.cyan
Qt.magenta
Qt.yellow
Qt.darkYellow
Qt.gray

可以通过指定 RGB 或 CMYK 或 HSV 值来选择自定义颜色。

示例

以下示例实现其中一些方法。

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore 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 Pyth
		on")
      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("python.jpg"))
      qp.fillRect(200,175,150,100,QBrush(Qt.SolidPattern))
      qp.end()
		
def main():
   app = QApplication(sys.argv)
   ex = Example()
   sys.exit(app.exec_())
	
if __name__ == '__main__':
   main()

以上代码产生以下输出:

BrushStyle Constants Output

PyQt - QClipboard

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

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

以下是常用剪贴板类方法:

序号 方法与说明
1

clear()

清除剪贴板内容

2

setImage()

将 QImage 复制到剪贴板

3

setMimeData()

将 MIME 数据设置为剪贴板

4

setPixmap()

将 Pixmap 对象复制到剪贴板

5

setText()

将 QString 复制到剪贴板

6

text()

从剪贴板检索文本

与剪贴板对象关联的信号为:

序号 方法和描述
1

dataChanged()

每当剪贴板数据更改时

示例

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

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

QClipboard Output1 QClipboard Output2 QClipboard Output3

PyQt - QPixmap 类

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

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

可以读取到 QPixmap 对象中的图像文件类型如下:

BMP Windows 位图
GIF 图形交换格式(可选)
JPG 联合图像专家组
JPEG 联合图像专家组
PNG 便携式网络图形
PBM 便携式位图
PGM 便携式灰度图
PPM 便携式像素图
XBM X11 位图
XPM X11 像素图

以下方法可用于处理 QPixmap 对象:

序号 方法与说明
1

copy()

从 QRect 对象复制 pixmap 数据

2

fromImage()

将 QImage 对象转换为 QPixmap

3

grabWidget()

从给定窗口部件创建 pixmap

4

grabWindow()

创建窗口中数据的 pixmap

5

load()

将图像文件加载为 pixmap

6

save()

将 QPixmap 对象保存为文件

7

toImage()

将 QPixmap 转换为 QImage

QPixmap 最常见的用途是在标签/按钮上显示图像。

示例

以下示例显示使用 setPixmap() 方法在 QLabel 上显示的图像。完整的代码如下:

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

def window():
   app = QApplication(sys.argv)
   win = QWidget()
   l1 = QLabel()
   l1.setPixmap(QPixmap("python.jpg"))
	
   vbox = QVBoxLayout()
   vbox.addWidget(l1)
   win.setLayout(vbox)
   win.setWindowTitle("QPixmap Demo")
   win.show()
   sys.exit(app.exec_())
	
if __name__ == '__main__':
   window()

以上代码产生以下输出:

QPixmap Class Output
广告