前言

这里是pyQt5的简单开发手册


总述:PyQt 框架架构与核心价值

PyQt 是 Python 语言的 Qt 框架绑定,结合了 Python 的简洁高效与 Qt 的强大功能,用于开发跨平台桌面应用嵌入式界面。其技术核心建立在四大支柱之上:

  1. 信号与槽机制 - 事件驱动的通信系统
  2. 窗口部件体系 - 丰富的 GUI 组件库
  3. 模型/视图架构 - 数据与显示的分离
  4. 多线程支持 - QThread 与线程安全

核心优势

  • 跨平台性:Windows/macOS/Linux/嵌入式系统
  • 商业友好:GPL 和商业双许可证
  • Qt Designer:可视化界面设计工具
  • 丰富组件:超过 600 个可直接使用的类
1
2
3
4
5
6
7
graph TD
A[PyQt核心] --> B[信号与槽]
A --> C[窗口部件]
A --> D[模型/视图]
A --> E[多线程]
A --> F[绘图系统]
A --> G[数据库集成]

一、信号与槽机制(事件驱动核心)

1. 基本连接方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from PyQt5.QtCore import QObject, pyqtSignal

class Sender(QObject):
# 定义信号
signal_example = pyqtSignal(str)

def trigger_signal(self):
self.signal_example.emit("Hello PyQt!")

class Receiver(QObject):
def handle_signal(self, message):
print("Received:", message)

sender = Sender()
receiver = Receiver()

# 连接信号与槽
sender.signal_example.connect(receiver.handle_signal)
sender.trigger_signal() # 输出: Received: Hello PyQt!

2. 内置信号使用

1
2
3
4
5
button = QPushButton("Click me")
button.clicked.connect(lambda: print("Button clicked!"))

slider = QSlider(Qt.Horizontal)
slider.valueChanged.connect(lambda value: print(f"Slider value: {value}"))

二、窗口部件(Widgets)体系

1. 基础窗口创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel

app = QApplication(sys.argv)

# 主窗口
window = QMainWindow()
window.setWindowTitle("PyQt Demo")
window.setGeometry(100, 100, 800, 600) # (x, y, width, height)

# 标签组件
label = QLabel("Hello PyQt!", window)
label.move(50, 50)

window.show()
sys.exit(app.exec_())

2. 常用组件函数速查

组件类 关键函数 功能说明
QPushButton setText(str) 设置按钮文本
clicked.connect(func) 点击事件连接
QLabel setPixmap(QPixmap) 设置图片显示
setAlignment(Qt.AlignCenter) 设置文本对齐
QLineEdit text() 获取输入文本
setPlaceholderText(str) 设置占位提示文本
QComboBox addItem(str) 添加下拉选项
currentText() 获取当前选中项
QCheckBox setChecked(bool) 设置选中状态
stateChanged.connect(func) 状态改变事件
QProgressBar setRange(min, max) 设置进度范围
setValue(int) 设置当前进度值

三、布局管理系统

1. 基础布局使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QGridLayout

# 垂直布局
v_layout = QVBoxLayout()
v_layout.addWidget(QPushButton("Top"))
v_layout.addWidget(QPushButton("Bottom"))

# 水平布局
h_layout = QHBoxLayout()
h_layout.addWidget(QPushButton("Left"))
h_layout.addWidget(QPushButton("Right"))

# 网格布局
grid = QGridLayout()
grid.addWidget(QLabel("Name:"), 0, 0)
grid.addWidget(QLineEdit(), 0, 1)
grid.addWidget(QLabel("Age:"), 1, 0)
grid.addWidget(QSpinBox(), 1, 1)

# 嵌套布局
main_layout = QVBoxLayout()
main_layout.addLayout(h_layout)
main_layout.addLayout(grid)

2. 布局管理函数

函数 说明
addWidget(widget) 添加控件
addLayout(layout) 嵌套子布局
setSpacing(int) 设置控件间距
setContentsMargins(l,t,r,b) 设置布局边距
setStretchFactor(index, factor) 设置拉伸因子

四、模型/视图架构

1. QListView 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PyQt5.QtCore import QStringListModel

# 创建数据模型
model = QStringListModel()
model.setStringList(["Apple", "Banana", "Orange"])

# 创建视图
list_view = QListView()
list_view.setModel(model)

# 选择变化信号
list_view.selectionModel().selectionChanged.connect(
lambda selected: print(selected.indexes()[0].data())
)

2. 自定义模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from PyQt5.QtCore import QAbstractTableModel, Qt

class CustomModel(QAbstractTableModel):
def __init__(self, data):
super().__init__()
self._data = data

def rowCount(self, parent):
return len(self._data)

def columnCount(self, parent):
return len(self._data[0])

def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
return self._data[index.row()][index.column()]

# 使用自定义模型
data = [["John", 30], ["Alice", 25]]
model = CustomModel(data)
table_view = QTableView()
table_view.setModel(model)

五、绘图与图形视图框架

1. QPainter 基础绘图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class CustomWidget(QWidget):
def paintEvent(self, event):
painter = QPainter(self)

# 绘制矩形
painter.setBrush(QColor(200, 0, 0))
painter.drawRect(10, 10, 100, 100)

# 绘制文本
painter.setFont(QFont("Arial", 16))
painter.drawText(50, 150, "Hello PyQt")

# 绘制路径
path = QPainterPath()
path.moveTo(50, 200)
path.cubicTo(100, 100, 200, 200, 250, 150)
painter.drawPath(path)

2. QGraphicsScene 高级图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
scene = QGraphicsScene()
scene.setSceneRect(0, 0, 400, 300)

# 添加图形项
rect = scene.addRect(50, 50, 100, 100, QPen(Qt.blue), QBrush(Qt.yellow))
ellipse = scene.addEllipse(200, 100, 80, 80, QPen(Qt.red))

# 添加文本
text = scene.addText("Graphics View", QFont("Arial", 14))
text.setPos(100, 200)

# 视图显示
view = QGraphicsView(scene)
view.show()

六、多线程与并发

1. QThread 使用模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Worker(QObject):
finished = pyqtSignal()
progress = pyqtSignal(int)

def run(self):
for i in range(1, 101):
time.sleep(0.1)
self.progress.emit(i)
self.finished.emit()

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.thread = QThread()
self.worker = Worker()
self.worker.moveToThread(self.thread)

self.thread.started.connect(self.worker.run)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.thread.finished.connect(self.thread.deleteLater)

btn_start = QPushButton("Start", self)
btn_start.clicked.connect(self.thread.start)

2. 线程间通信

1
2
3
4
5
6
# 主线程更新UI
self.worker.progress.connect(self.update_progress)

def update_progress(self, value):
# 此方法在主线程执行
self.progress_bar.setValue(value)

七、数据库集成

1. SQL 数据库操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from PyQt5.QtSql import QSqlDatabase, QSqlQuery

# 创建数据库连接
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("mydatabase.db")
if not db.open():
print("Database error:", db.lastError().text())

# 执行查询
query = QSqlQuery()
query.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")
query.exec("INSERT INTO users (name) VALUES ('John')")

# 读取数据
query.exec("SELECT * FROM users")
while query.next():
print(query.value("id"), query.value("name"))

2. 模型视图集成

1
2
3
4
5
6
7
8
model = QSqlTableModel()
model.setTable("users")
model.select()

# 显示在表格中
table_view = QTableView()
table_view.setModel(model)
table_view.show()

高级特性与最佳实践

1. 样式表定制(QSS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 全局样式
app.setStyleSheet("""
QMainWindow {
background-color: #2c3e50;
}
QPushButton {
background-color: #3498db;
color: white;
border-radius: 5px;
padding: 5px 10px;
}
QPushButton:hover {
background-color: #2980b9;
}
""")

# 单个组件样式
button.setStyleSheet("""
QPushButton {
border: 2px solid #e74c3c;
font-weight: bold;
}
""")

2. 国际化支持

1
2
3
4
5
6
7
# 创建翻译器
translator = QTranslator()
translator.load("app_zh_CN.qm")
app.installTranslator(translator)

# 标记可翻译文本
button.setText(QCoreApplication.translate("Main", "Click Me"))

3. 插件系统

1
2
3
4
5
6
7
8
9
10
11
12
# 创建插件接口
class PluginInterface:
def initialize(self) -> bool: ...
def do_action(self): ...

# 加载插件
plugin_dir = QDir("./plugins")
for filename in plugin_dir.entryList(["*.so", "*.dll"]):
loader = QPluginLoader(plugin_dir.filePath(filename))
plugin = loader.instance()
if isinstance(plugin, PluginInterface):
plugin.initialize()

总结:PyQt 应用架构与开发模式

PyQt 应用核心结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.init_ui()

def init_ui(self):
# 1. 创建组件
# 2. 设置布局
# 3. 连接信号槽
# 4. 设置窗口属性
self.setWindowTitle("PyQt App")
self.show()

if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())

开发工作流

  1. 界面设计:使用 Qt Designer 创建 .ui 文件
  2. 转换代码pyuic5 input.ui -o output.py
  3. 业务逻辑:继承生成类实现功能
  4. 资源管理:使用 pyrcc5 编译资源文件
  5. 打包分发pyinstaller --windowed app.py

性能优化技巧

  1. 延迟加载:大型组件按需初始化

    1
    2
    3
    def show_tab(self, index):
    if index == 2 and not self.tab2_loaded:
    self.init_tab2()
  2. 列表优化:大数据集使用模型/视图

    1
    self.list_view.setUniformItemSizes(True)  # 提高滚动性能
  3. 绘图优化:避免在 paintEvent 中创建对象

    1
    2
    3
    def paintEvent(self, event):
    # 错误: 在paintEvent中创建QPen/QBrush
    # 正确: 预创建绘图对象
  4. 内存管理:正确处理对象生命周期

    1
    2
    3
    4
    5
    # 自动删除
    obj.deleteLater()

    # 父子关系自动销毁
    child_widget = QWidget(parent=self)

PyQt 与 PySide 对比

特性 PyQt PySide
许可证 GPL/商业许可 LGPL
开发商 Riverbank Computing Qt 官方
API兼容 兼容 Qt4/Qt5 兼容 Qt4/Qt5/Qt6
信号语法 pyqtSignal Signal
社区支持 成熟,文档丰富 官方支持,发展迅速
部署大小 稍大 稍小