pyqt5笔记
PyQt中有非常多的功能模块,开发中最常用的功能模块主要有三个:
-
QtCore包含了核心的非GUI的功能·主要和时间、文件与文件夹、各种数据、流、URLmime类文件、进程与线程一起使用
-
QtGui:包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类
-
QtWidgets:包含了一些列创建桌面应用的UI元素
设置父类的两种方式:
btn = QPushButton("按钮")
btn.setParent(w) #绑定父类
或
btn = QPushButton("按钮",w)
QtWidgets下的小控件:
1.按钮
btn = QPushButton("按钮")
btn.setParent(w) #绑定父类
btn.clicked.connect(exit) #为按钮绑定事件(函数)
2.文本标签
label = QLabel("齐齐")
label.setParent(w)
若要修改字体属性
使用 QFont 类可以设置字体的属性,例如大小、粗细、字体族等。
from PyQt5.QtGui import QFont
# 创建一个 QLabel
label = QLabel("Hello, World!")
# 设置字体
font = QFont()
font.setPointSize(20) # 设置字体大小为 20
font.setBold(True) # 设置字体加粗
label.setFont(font) # 应用字体
修改文字排列方式
from PyQt5.QtCore import Qt
# 创建一个 QLabel
label = QLabel("Hello, World!")
# 设置文字居中对齐
label.setAlignment(Qt.AlignCenter)
Qt.AlignLeft:左对齐Qt.AlignRight:右对齐Qt.AlignCenter:居中对齐Qt.AlignTop:顶部对齐Qt.AlignBottom:底部对齐
3.图片标签
QPixmap 是 PyQt5 中用于处理图像的类,可以加载常见的图片格式(如 PNG、JPG 等)。
from PyQt5.QtGui import QPixmap
from PyQt5.Widget import QLabel
#创建一个QLabel
image_label = QLabel(self)#self是指定父控件.必须是一个 QWidget 或其子类的实例。
#加载图片
pixmap = QPixmap("example.jpg")
#将图片设置为QLabel的内容
self.image_label.setPixmap(pixmap)
若要设置图片尺寸
#创建一个QLabel
image_label = QLabel(self)#self是指定父控件.必须是一个 QWidget 或其子类的实例。
#加载图片
pixmap = QPixmap("example.jpg")
#设置图片尺寸
scaled_pixmap = pixmap.scaled(300,300)
#将缩放后的图片设置为QLabel的内容
self.image_label.setPixmap(scaled_pixmap)
4.输入框
edit = QLineEdit("请输入账号:",w)
edit.setGeometry(20,20,300,30)
edit.setPlaceholderText("请输入内容") #可以在用户未输入内容时显示文字
多行输入框
reviewEdit = QTextEdit()
5.空白占位符
QSpacerItem(width, height, horizontalPolicy, verticalPolicy)
参数说明
horizontalPolicy:
- 控制占位符在水平方向上的大小策略。
- 类型为
QSizePolicy.Policy,常用的值包括:QSizePolicy.Minimum:占位符的大小不能小于初始宽度。QSizePolicy.Expanding:占位符可以扩展以填充可用空间。QSizePolicy.Fixed:占位符的大小固定为初始宽度。QSizePolicy.Preferred:占位符的大小优先使用初始宽度,但可以扩展。
verticalPolicy:
- 控制占位符在垂直方向上的大小策略。
- 类型为
QSizePolicy.Policy,常用的值与horizontalPolicy相同。
layout = QGridLayout()
spacer = QSpacerItem(40, 20) # 宽度 40,高度 20
layout.addItem(spacer, 1, 0, 1, 2) # 占据第 1 行,跨越 2 列
6.QSizePolicy 分配控件在布局中所占空间
水平策略 (HorizontalPolicy) 和垂直策略 (VerticalPolicy)
- 这两个属性分别控制控件在水平和垂直方向上的大小行为。
- 常用的策略包括:
QSizePolicy.Fixed:控件的大小固定为初始大小。QSizePolicy.Minimum:控件的大小不能小于初始大小。QSizePolicy.Maximum:控件的大小不能大于初始大小。QSizePolicy.Preferred:控件的大小优先使用初始大小,但可以扩展。QSizePolicy.Expanding:控件可以扩展以填充可用空间。QSizePolicy.MinimumExpanding:控件的大小不能小于初始大小,但可以扩展以填充可用空间。QSizePolicy.Ignored:控件的大小会被忽略,布局会尽可能分配空间。
7.QStackedWidget 容器控件,可以包含多个子界面(QWidget),但每次只会显示一个界面
通过索引切换界面
self.stacked_widget.setCurrentIndex(2) # 切换到第三个界面
直接指定界面对象(QWidget)来切换界面
self.stacked_widget.setCurrentWidget(self.page3) # 切换到 page3 界面
提示:切换前需要确保页面已被添加
self.stackedWidget.addWidget(self.page0)
8.QTableWidget 表单(表格)控件
row是行,column是列
1.基本概念
QTableWidget管理QTableWidgetItem对象来表示单元格内容。- 可以用
setCellWidget()放入控件(如按钮、复选框等)。 - 常用操作:设置行列、插入删除行、修改单元格内容、设置表头、监听信号等。
2.表结构相关方法
setRowCount(count) # 设置总行数
rowCount() # 获取当前行数
setColumnCount(count) # 设置总列数
columnCount() # 获取当前列数
insertRow(row_index) # 插入一行
removeRow(row_index) # 删除一行
setSpan(row, column, rowSpan, colSpan) # 合并单元格
3.单元格操作
setItem(row, column, QTableWidgetItem) # 设置单元格内容(只能接受字符串)
item(row, column) # 获取单元格内容对象,锁定某个单元格
takeItem(row, column) # 移除单元格但不删除对象
setCellWidget(row, column, QWidget) # 放入控件
cellWidget(row, column) # 获取控件
4.表头相关
setHorizontalHeaderItem(col, QTableWidgetItem) # 设置水平表头
horizontalHeader() # 获取 QHeaderView 对象
verticalHeader() # 获取垂直表头对象
常用表头设置:
header = table.horizontalHeader()
header.setSectionResizeMode(0, QHeaderView.ResizeToContents) # 自动宽度
header.setSectionResizeMode(1, QHeaderView.Stretch) # 拉伸列宽
table.setColumnWidth(0, 120) # 固定宽度
5.编辑与选择行为
setEditTriggers(QAbstractItemView.NoEditTriggers) # 禁止编辑
setSelectionBehavior(QAbstractItemView.SelectRows) # 选中整行
setSelectionMode(QAbstractItemView.SingleSelection) # 单选模式
setSortingEnabled(True) # 启用排序
6.外观设置
setShowGrid(True) # 是否显示网格线
setAlternatingRowColors(True) # 交替行颜色
setWordWrap(True) # 自动换行
setCornerButtonEnabled(False) # 隐藏左上角按钮
setStyleSheet("QTableWidget { ... }")# 使用样式表
7.清空与重置
clear() # 清空表头和内容
clearContents() # 清空内容保留结构
setRowCount(0) # 快速清空所有行
8.排序与查找
sortItems(column, Qt.AscendingOrder) # 按列排序
findItems("文本", Qt.MatchContains) # 查找文本
9.模型访问(高级)
model() # 获取内部模型
setModel(model) # 替换模型(通常不建议)
10.常用信号(事件)
from PyQt5.QtWidgets import QTableWidgetItem
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush, QColor, QFont
# 1. 创建 QTableWidgetItem 实例
item = QTableWidgetItem("文本")
# 2. 设置文本对齐方式
# 使用 Qt.AlignCenter 标志将单元格中的文本设置为水平和垂直居中。
# 如果只需要水平居中,可以使用 Qt.AlignHCenter。
item.setTextAlignment(Qt.AlignCenter)
# 3. 设置单元格的标志(Flags)和交互属性
# 标志决定了用户可以对该单元格进行哪些操作。
# Qt.ItemIsSelectable: 允许用户选中该单元格。
# Qt.ItemIsEnabled: 允许用户与该单元格进行交互(例如,如果可编辑则允许编辑)。
# 组合使用这两个标志表示单元格是可见、可选中、可用的,但默认不可编辑。
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
# 4. 设置单元格的背景颜色
# 创建 QBrush 和 QColor 对象,将单元格的背景色设置为浅蓝色(lightblue)。
item.setBackground(QBrush(QColor("lightblue")))
# 5. 设置单元格内容的字体
# 创建 QFont 对象,将文本字体设置为“微软雅黑”,字号为 10 磅。
item.setFont(QFont("Microsoft YaHei", 10))
# 6. 获取单元格中的文本内容
# 获取并返回 item 中当前设置的字符串内容,即 "文本"。
text = item.text()
# 7. 存储自定义用户数据
# 使用 Qt.UserRole 角色存储与单元格内容无关的自定义数据。
# 这里的 "自定义数据" 是一个 Python 字符串,可以存储任何 Python 对象。
# 之后可以通过 item.data(Qt.UserRole) 来读取这个数据。
item.setData(Qt.UserRole, "自定义数据")
11.QTableWidgetItem 常用方法(设置文本对齐方式)
# 1. 创建 QTableWidgetItem 实例
item = QTableWidgetItem("文本")
# 2. 设置文本对齐方式
# 使用 Qt.AlignCenter 标志将单元格中的文本设置为水平和垂直居中。
# 如果只需要水平居中,可以使用 Qt.AlignHCenter。
item.setTextAlignment(Qt.AlignCenter)
# 3. 设置单元格的标志(Flags)和交互属性
# 标志决定了用户可以对该单元格进行哪些操作。
# Qt.ItemIsSelectable: 允许用户选中该单元格。
# Qt.ItemIsEnabled: 允许用户与该单元格进行交互(例如,如果可编辑则允许编辑)。
# 组合使用这两个标志表示单元格是可见、可选中、可用的,但默认不可编辑。
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
# 4. 设置单元格的背景颜色
# 创建 QBrush 和 QColor 对象,将单元格的背景色设置为浅蓝色(lightblue)。
item.setBackground(QBrush(QColor("lightblue")))
# 5. 设置单元格内容的字体
# 创建 QFont 对象,将文本字体设置为“微软雅黑”,字号为 10 磅。
item.setFont(QFont("Microsoft YaHei", 10))
# 6. 获取单元格中的文本内容
# 获取并返回 item 中当前设置的字符串内容,即 "文本"。
text = item.text()
# 7. 存储自定义用户数据
# 使用 Qt.UserRole 角色存储与单元格内容无关的自定义数据。
# 这里的 "自定义数据" 是一个 Python 字符串,可以存储任何 Python 对象。
# 之后可以通过 item.data(Qt.UserRole) 来读取这个数据。
item.setData(Qt.UserRole, "自定义数据")
12.实战技巧与性能优化
- 批量填充数据前关闭排序和信号:
table.setSortingEnabled(False)
table.blockSignals(True)
# 批量插入数据
table.blockSignals(False)
table.setSortingEnabled(True)
- 使用
setRowCount(n)比循环插入更快。 - 大量数据建议使用
QTableView + QAbstractTableModel。 setCellWidget()会降低性能,避免大量控件。- 清空时用
setRowCount(0)效率最高。
13.常见需求示例
动态添加一行
def add_row(table, title, duration):
row = table.rowCount()
table.insertRow(row)
table.setItem(row, 0, QTableWidgetItem(str(row + 1)))
table.setItem(row, 1, QTableWidgetItem(title))
table.setItem(row, 2, QTableWidgetItem(duration))
批量填充数据
def load_data(table, data_list):
table.setSortingEnabled(False)
table.blockSignals(True)
table.setRowCount(len(data_list))
for r, (id_, title, dur) in enumerate(data_list):
table.setItem(r, 0, QTableWidgetItem(id_))
table.setItem(r, 1, QTableWidgetItem(title))
table.setItem(r, 2, QTableWidgetItem(dur))
table.blockSignals(False)
table.setSortingEnabled(True)
获取选中行数据
def get_selected_rows(table):
rows = set(index.row() for index in table.selectedIndexes())
result = []
for r in sorted(rows):
id_ = table.item(r,0).text() if table.item(r,0) else ""
title = table.item(r,1).text() if table.item(r,1) else ""
duration = table.item(r,2).text() if table.item(r,2) else ""
result.append((r, id_, title, duration))
return result
设置单元格不可编辑
item = QTableWidgetItem("固定内容")
item.setFlags(item.flags() & ~Qt.ItemIsEditable)
table.setItem(row, col, item)
在单元格中放按钮
btn = QPushButton("删除")
btn.clicked.connect(lambda _, r=row: table.removeRow(r))
table.setCellWidget(row, 3, btn)
按列排序并更新序号
table.sortItems(1, Qt.AscendingOrder)
for r in range(table.rowCount()):
item = table.item(r, 0) or QTableWidgetItem()
item.setText(str(r+1))
table.setItem(r, 0, item)
扩展方向
- 想在单元格内显示图标、进度条、颜色条? → 使用
QStyledItemDelegate - 需要高性能大数据表格? → 使用
QTableView + QAbstractTableModel - 想要导出表格为 CSV 或 Excel? → 遍历
item(row, col)结合pandas保存。
结论
| 场景 | 推荐方法 |
|---|---|
| 静态表格 | 使用 setRowCount() 一次性填充 |
| 动态表格 | 使用 insertRow() 逐行添加 |
| 清空表格 | 使用 setRowCount(0) |
| 禁止编辑 | setEditTriggers(QAbstractItemView.NoEditTriggers) |
| 自动列宽 | horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) |
如何添加数据
序号 | 标题 | 使用时长
动态添加数据需要用到以下方法
setRowCount(n) # 设置总行数
insertRow(row_index) # 在指定位置插入一行
setItem(row, col, item) # 在指定位置放入单元格内容
常用写法:
# 添加一行数据
row = ui.tableWidget.rowCount() # 当前已有行数
ui.tableWidget.insertRow(row) # 在最后插入一行
# 设置三列内容
ui.tableWidget.setItem(row, 0, QTableWidgetItem(str(row + 1))) # 序号
ui.tableWidget.setItem(row, 1, QTableWidgetItem("测试标题")) # 标题
ui.tableWidget.setItem(row, 2, QTableWidgetItem("120秒")) # 使用时长
示例:
# 待添加的数据
data = [
("1", "浏览器", "300秒"),
("2", "Visual Studio Code", "1800秒"),
("3", "PyCharm", "900秒")
]
ui.tableWidget.setRowCount(len(data)) # 一次性设置行数
for row, (id_, title, duration) in enumerate(data):
ui.tableWidget.setItem(row, 0, QTableWidgetItem(id_))
ui.tableWidget.setItem(row, 1, QTableWidgetItem(title))
ui.tableWidget.setItem(row, 2, QTableWidgetItem(duration))
添加和删除行(动态)
# 添加行,系统会自动扩展行数
self.tableWidget.insertRow(row_index)
# 删除行
self.tableWidget.removeRow(row_index)
示例
def add_row(self, title, duration):
row = self.tableWidget.rowCount() # 当前行数
self.tableWidget.insertRow(row) # 追加一行
self.tableWidget.setItem(row, 0, QTableWidgetItem(str(row + 1)))
self.tableWidget.setItem(row, 1, QTableWidgetItem(title))
self.tableWidget.setItem(row, 2, QTableWidgetItem(duration))
实时更新表格示例
from PySide2.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, QPushButton, QVBoxLayout, QWidget
from mainWindow import Ui_MainWindow
import sys, random
class MyWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
# 示例按钮
self.add_btn = QPushButton("添加随机行", self)
layout = QVBoxLayout(self.centralwidget)
layout.addWidget(self.tableWidget)
layout.addWidget(self.add_btn)
self.add_btn.clicked.connect(self.add_random_row)
def add_random_row(self):
row = self.tableWidget.rowCount()
self.tableWidget.insertRow(row)
self.tableWidget.setItem(row, 0, QTableWidgetItem(str(row + 1)))
self.tableWidget.setItem(row, 1, QTableWidgetItem(f"程序{random.randint(1,100)}"))
self.tableWidget.setItem(row, 2, QTableWidgetItem(f"{random.randint(10,500)}秒"))
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MyWindow()
win.show()
sys.exit(app.exec_())
9.QListWidget 单列可供选择的列表控件
listWidget = QListWidget(Settings)
默认选中第一个菜单栏
listWidget.setCurrentRow(0) # 默认选中第一个菜单项
设置各选择项之间的间距
listWidget.setSpacing(5)
为列表增加新的行
listWidget.addItem("item"+str(i))
为列表的每一行附上双击事件
def on_click(item):
print("Clicked"+item.text())
ui.listWidget.itemDoubleClicked.connect(on_click)
为列表的每一行附上单击事件
for i in range(5):
ui.listWidget.addItem("item"+str(i))
ui.listWidget.item(i).clicked.connect(on_click)
10.QCheckBox 复选框
1. 基本概念
QCheckBox 是一个可选中或取消选中的复选框控件,可以用来让用户选择某个功能是否启用。
- 默认状态有两种:选中 / 未选中
- 可设置为三态复选框:选中 / 未选中 / 部分选中
2. 构造函数
checkbox = QCheckBox("显示标题", parent)
"显示标题":复选框旁显示的文本parent:父控件,一般是窗口或布局
3. 常用方法详解
| 方法 | 说明 | 示例 |
|---|---|---|
isChecked() |
返回复选框是否选中(布尔值) | checked = checkbox.isChecked() |
setChecked(bool) |
设置复选框选中或未选中 | checkbox.setChecked(True) |
toggle() |
切换选中状态 | checkbox.toggle() |
setText(str) |
设置复选框旁的文字 | checkbox.setText("启用功能") |
text() |
获取复选框的文字 | txt = checkbox.text() |
checkState() |
获取复选框状态,返回 0/1/2 | state = checkbox.checkState() |
setTristate(bool) |
设置是否允许三态 | checkbox.setTristate(True) |
setCheckState(Qt.CheckState) |
设置复选框状态(0=Unchecked, 1=PartiallyChecked, 2=Checked) | checkbox.setCheckState(Qt.PartiallyChecked) |
setEnabled(bool) |
设置是否可用 | checkbox.setEnabled(False) |
setVisible(bool) |
设置是否可见 | checkbox.setVisible(False) |
4. 常用信号
| 信号 | 说明 | 参数 |
|---|---|---|
stateChanged(int) |
状态发生变化时触发 | 0=未选中, 2=选中, 1=部分选中 |
toggled(bool) |
选中/取消选中时触发 | True/False |
示例:stateChanged
def on_state_changed(state):
if state == 2:
print("复选框选中")
elif state == 0:
print("复选框未选中")
else:
print("复选框部分选中")
checkbox.stateChanged.connect(on_state_changed)
示例:toggled
def on_toggled(checked):
if checked:
print("启用功能")
else:
print("禁用功能")
checkbox.toggled.connect(on_toggled)
5. 三态复选框(可选)
from PySide2.QtCore import Qt
checkbox.setTristate(True) # 开启三态
checkbox.setCheckState(Qt.PartiallyChecked) # 设置为部分选中
- 未选中 →
Qt.Unchecked(0) - 部分选中 →
Qt.PartiallyChecked(1) - 选中 →
Qt.Checked(2)
野生小控件
创建状态栏
self.status=self.statusBar()
self.status.showMessage("这是状态栏展示",5000)#要展示的消息,毫秒数(1000ms=1s)
设置控件的位置:
#显示位置与大小:x,y,w,h 坐标和宽高
#左上角为(0,0)
label.setGeometry(20,20,30,30)
可以通过resize重新设置窗口大小:
app = QApplication(sys.argv) #创建程序,与app.exec_()相对应
w = QWidget() #控件(主窗口控件)
#设置窗口标题
w.setWindowTitle("第一个qt程序")
#设置主窗口大小(固定)
w.resize(600,300)
#展示窗口
w.show()
#程序进行循环等待状态
app.exec_()
w.move(x,y)可以用来移动主窗口在屏幕上显示的位置
| 特性 | addWidget |
addItem |
|---|---|---|
| 作用对象 | QWidget 或其子类(如按钮、标签等) |
QLayoutItem 或其子类(如占位符等) |
| 使用场景 | 添加具体的控件 | 添加布局项(如占位符、空白区域等) |
| 灵活性 | 只能添加控件 | 可以添加任何 QLayoutItem,更灵活 |
| 常见用途 | 添加按钮、标签、输入框等 | 添加占位符、空白区域等 |
野生函数
addAction()
addAction() 是 QWidget、QMenu、QToolBar 等类的方法,不同类略有差异:
| 类 | 说明 |
|---|---|
QWidget |
给窗口或控件添加动作,主要用于快捷键触发或上下文菜单。 |
QMenu |
给菜单添加 QAction,会在菜单中生成对应菜单项。 |
QToolBar |
给工具栏添加 QAction,会在工具栏生成对应按钮。 |
注:
QAction本身不显示,addAction()是把QAction显示在界面上的方法。
方法签名(以QMenu为例)
QAction QMenu.addAction(QAction *action)
QAction QMenu.addAction(const QString &text, QObject *receiver, const char *member)
- 第一种:已有QAction对象
menu.addAction(action)
- 第二种:直接创建并绑定槽
menu.addAction("打开", self, slot_function)
注:第2种写法会内部生成一个 QAction 并返回。
常见用法
1️⃣ 菜单中添加选项
from PySide2.QtWidgets import QMainWindow, QApplication, QMenu, QAction
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("菜单示例")
# 创建菜单
menu_file = QMenu("文件", self)
self.menuBar().addMenu(menu_file)
# 创建 QAction
action_open = DoubleClicked("打开", self)
action_open.triggered.connect(self.open_file)
# 添加到菜单
menu_file.addAction(action_open)
def open_file(self):
print("打开文件操作")
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
2️⃣ 工具栏中添加按钮
from PySide2.QtWidgets import QMainWindow, QApplication, QToolBar, QAction
from PySide2.QtGui import QIcon
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("工具栏示例")
# 创建工具栏
toolbar = QToolBar("工具栏")
self.addToolBar(toolbar)
# 创建 QAction
action_save = QAction(QIcon("save.png"), "保存", self)
action_save.triggered.connect(self.save_file)
# 添加到工具栏
toolbar.addAction(action_save)
def save_file(self):
print("保存操作")
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
3️⃣ QWidget 中添加动作(快捷键触发)
from PySide2.QtWidgets import QMainWindow, QApplication, QAction
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("快捷键示例")
# 创建 QAction
action_quit = QAction("退出", self)
action_quit.setShortcut("Ctrl+Q")
action_quit.triggered.connect(self.close)
# 添加到窗口(注册快捷键)
self.addAction(action_quit)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
布局
-
grid布局
方法:
addWidget(widget,int row,int col,int alignment=0) #添加的空间、控件的行数、控件的列数、对齐方式 addWidget(widget,int fromRow,int fromColumn,int rowSoan,int columnSpan,Qt.Alignment int alignment=0) #添加的空间、控件的起始行数、控件的起始列数、控件跨越的行数、控件跨越的列数、对齐方式grid.setSpacing(10)#设置布局中控件的间距
-
QHBoxLayout水平布局
设置控件间的间距
layout = QHBoxLayout() layout.setSpacing(5)设置控件大小
widget.setFixedSize(width, height)#用户无法调整
widget.resize(width, height)#设置控件初始大小,用户仍可调整
widget.setMinimumSize(min_width, min_height)#设置最大和最小的范围
widget.setMaximumSize(max_width, max_height)
对齐方式
-
水平对齐
Qt.AlignLeft:左对齐。 Qt.AlignRight:右对齐。 Qt.AlignHCenter:水平居中对齐。 Qt.AlignJustify:两端对齐。 -
垂直对齐
Qt.AlignTop:顶部对齐。 Qt.AlignBottom:底部对齐。 Qt.AlignVCenter:垂直居中对齐。 -
组合对齐
水平和垂直对齐可以组合使用,例如:
Qt.AlignLeft | Qt.AlignTop:左上对齐。 Qt.AlignRight | Qt.AlignBottom:右下对齐。 Qt.AlignHCenter | Qt.AlignVCenter:水平和垂直都居中对齐(默认行为)。
动作
QAction
提供了一种把命令逻辑从界面组件(菜单、按钮、快捷键等)中分离出来的机制。
常用属性 / 方法(按用途分组)
创建与基本
QAction(text, parent) — 构造。
setText(str)/text()— 显示文字。setIcon(QIcon)/icon()— 图标(用于工具栏或菜单)。setEnabled(bool)/isEnabled()— 启用 / 禁用。setVisible(bool)/isVisible()— 是否显示(菜单或工具栏中)。setToolTip(str)— 鼠标悬停显示(工具栏按钮)。setStatusTip(str)— 状态栏提示(鼠标悬停时显示在窗口状态栏)。setWhatsThis(str)— “What's This?” 帮助文本。
快捷键
setShortcut(QKeySequence or str)— 设置快捷键(例如"Ctrl+S")。setShortcuts(list_of_QKeySequence)— 多快捷键可同时设置。shortcut()/shortcuts()— 获取。
可选/切换
setCheckable(bool)— 是否可勾选(开/关行为)。isCheckable()、isChecked()、setChecked(bool)— 读写勾选状态。toggled(bool)信号 — 可勾选动作状态改变时发出(与triggered(bool)类似)。
数据与元信息
setData(QVariant)/data()— 给动作挂载任意数据(常用于在同一槽中区分来源)。setObjectName(str)— 可用于查找、调试或样式表。
管理
setMenu(QMenu)— 把QAction作为带子菜单的占位(较少用)。deleteLater()— 清理。
常用信号(重要)
triggered(bool checked=False)— 用户触发(点击菜单项、工具栏按钮、按下快捷键)。如果动作是 checkable,会传入checked状态;否则为False。
常与connect(槽函数)连用:.triggered.connect(self.open_settings_window)trigger():主动触发triggered.connect信号,执行指定动作。用法见以下示例
toggled(bool checked)— 仅当checkable=True且勾选状态变化时触发。hovered()— 鼠标悬停在该动作可视化元素上时触发(例如菜单项)。changed()— 当动作的属性(如文本、图标、启用状态等)被修改时触发。
注意:
triggered可用于非 checkable 和 checkable 两种场景;对 checkable 更推荐使用toggled来处理勾选逻辑。
trigger用法示例:
# 1️⃣ 创建 QAction(不加到菜单或工具栏)
self.action_settings = QAction("打开设置", self)
self.action_settings.triggered.connect(self.open_settings_window)
# 2️⃣ 绑定已存在的按钮触发 QAction
self.existing_button.clicked.connect(self.action_settings.trigger)
常见用法与代码示例
1) 把动作添加到菜单与工具栏(经典)
from PySide2.QtWidgets import QMainWindow, QAction
action_exit = QAction("退出", self)
action_exit.setShortcut("Ctrl+Q")
action_exit.setStatusTip("退出程序")
action_exit.triggered.connect(self.close)
# 添加到菜单
self.ui.menu_File.addAction(action_exit)
# 添加到工具栏
self.toolbar.addAction(action_exit)
效果:菜单项、工具栏按钮、快捷键都共享同一行为。
2) 可勾选动作(Toggle)
action_autorun = QAction("开机自启", self)
action_autorun.setCheckable(True)
action_autorun.setChecked(False) # 默认为未勾选
action_autorun.toggled.connect(self.on_autorun_toggled)
def on_autorun_toggled(self, checked):
# 保存到配置或执行启用/禁用逻辑
print("开机自启:", checked)
triggered(bool) 也能接到 checked 值,但 toggled 更语义化。
3) 将若干互斥的动作做成“单选”风格(QActionGroup)
from PySide2.QtWidgets import QActionGroup
group = QActionGroup(self)
group.setExclusive(True) # 单选
a1 = QAction("选项 A", self); a1.setCheckable(True); group.addAction(a1)
a2 = QAction("选项 B", self); a2.setCheckable(True); group.addAction(a2)
a1.triggered.connect(lambda: print("选 A"))
a2.triggered.connect(lambda: print("选 B"))
常用于视图显示模式(列表/表格/树等)。
4) 在右键菜单 / context menu 中使用
def contextMenuEvent(self, event):
menu = QMenu(self)
act_copy = QAction("复制", self)
act_copy.triggered.connect(self.copy)
menu.addAction(act_copy)
menu.exec_(event.globalPos())
5) 动态启用/禁用动作(根据状态)
# 假设没有选定项时禁用“删除”
self.action_delete.setEnabled(False)
self.table.selectionModel().selectionChanged.connect(self.on_selection_changed)
def on_selection_changed(self, selected, deselected):
self.action_delete.setEnabled(self.table.selectionModel().hasSelection())
6) 把额外数据挂在动作上用于统一槽(用 setData/getData)
for i, name in enumerate(["apple", "banana", "cherry"]):
act = QAction(name, self)
act.setData(i) # 把索引挂在上面
act.triggered.connect(self.on_pick)
def on_pick(self):
act = self.sender()
idx = act.data()
print("picked:", idx)
推荐模式:在槽内用
self.sender()识别触发者,再用data()读取附带信息。
7) 快捷键与多快捷键
act_save = QAction("保存", self)
act_save.setShortcuts(["Ctrl+S", "F12"])
8) 与状态栏结合(StatusTip)
act = QAction("导出", self)
act.setStatusTip("导出当前数据到文件")
# 当鼠标悬停到菜单项/工具栏按钮时,主窗口的 statusBar() 会显示该文本
9) 不生成新的元素,仅通过QAction来统一逻辑(触发动作)
# 1️⃣ 创建 QAction(不加到菜单或工具栏)
self.action_settings = QAction("打开设置", self)
self.action_settings.triggered.connect(self.open_settings_window)
# 2️⃣ 绑定已存在的按钮触发 QAction
self.existing_button.clicked.connect(self.action_settings.trigger)
⚠️ 注意:
-
不调用 addAction() 就不会生成新的菜单项或工具栏按钮
-
通过 trigger() 可以把任何已有按钮点击转发给 QAction
信号参数细节(避免常见迷惑)
triggered()在非 checkable 时发出triggered(False);在 checkable 时发出triggered(True|False)。toggled()只在checkable=True时使用,参数为当前checked状态。hovered()无参数,只表示鼠标指向该动作(可用于显示高级提示)。
补充
1.pyqt5可以隐藏标题栏
self.setMenuBar(None) # 彻底移除菜单栏(无法恢复)
#将控件添加到布局中用addWidget
#而将另一个布局添加到一个布局里要用addLayout
addLayout(layout,stretch=0)
#stretch是拉伸因子,可以通过拉伸因子的值来调整布局占比
2.显示声明槽函数
from PySide2.QtCore import Slot
class MyWindow(QMainWindow):
@Slot() # 显式声明为槽
def on_button_clicked(self):
print("按钮被点击")
作用:
- 定义槽函数接受的参数类型,Qt 会在信号触发时自动校验参数类型,避免类型错误。
- 显式声明槽函数后,Qt 可以提前绑定信号与槽的连接方式,减少动态查找的开销,提升执行效率(尤其在频繁触发信号时)。
3.python3对类的继承进行了简化
class Page2(QWidget):
def __init__(self):
super().__init__()#这样写就可以了
layout = QVBoxLayout()
self.label = QLabel("这是界面 2")
layout.addWidget(self.label)
self.setLayout(layout)
4.所有可见的窗口都要依托QMainWindow()存在
常用操作
窗口最小化隐藏到托盘
from PySide2.QtGui import QIcon
from PySide2.QtCore import QEvent
from PyQt5.QtWidgets import QSystemTrayIcon
1.创建系统托盘图标
self.tray_icon = QSystemTrayIcon(QIcon("icon.png"), self)
self.tray_icon.show()
QSystemTrayIcon用于在系统任务栏显示图标。show()必须调用,否则图标不会显示,隐藏窗口后程序就“找不到”了。- 图标路径必须有效(Windows 建议
.ico,Linux/macOS.png可用)。 - 可以绑定菜单和点击事件:
# 创建托盘菜单
tray_menu = QMenu()
show_action = QAction("显示窗口")
show_action.triggered.connect(self.showNormal)
tray_menu.addAction(show_action)
self.tray_icon.setContextMenu(tray_menu)
2.拦截窗口最小化事件
def changeEvent(self, event):
if event.type() == QEvent.WindowStateChange:
if self.isMinimized():
self.hide()
- 当窗口最小化时,自动隐藏窗口。
QEvent.WindowStateChange事件检测窗口状态变化。isMinimized()检测窗口是否最小化。
3.托盘图标点击或菜单恢复窗口
self.tray_icon.activated.connect(self.on_tray_icon_activated)
def on_tray_icon_activated(self, reason):
if reason == QSystemTrayIcon.Trigger: # 单击托盘图标
self.showNormal()
self.activateWindow()
- 单击托盘图标恢复窗口。
showNormal()恢复窗口到正常大小。activateWindow()把窗口激活到前台。
4.保证隐藏后程序不退出
QApplication.setQuitOnLastWindowClosed(False)
- 默认关闭最后一个窗口会退出应用。
- 设置为
False后,即使窗口隐藏,应用仍在后台运行,托盘可操作。
使用base64内嵌图片
from PyQt5.QtGui import QIcon, QPixmap
# 示例:这里是一段 base64 编码(你可换成自己的)
icon_base64 = """
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABbUlEQVRYR+2WwQ3CMAyG...
""" # ⚠️注意:需换成完整的 Base64 数据
# 将 base64 转成 QPixmap
image_data = base64.b64decode(icon_base64)
pixmap = QPixmap()
pixmap.loadFromData(image_data)
# 创建 QIcon
icon = QIcon(pixmap)
...
closeEvent() 自定义捕获退出的方法
class MyMainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
# 启动监控线程
self.thread = threading.Thread(target=window_monitor, args=(self.tableWidget,))
self.thread.daemon = True # 主线程退出时自动结束
self.thread.start()
# 重写父类捕获退出的方法
def closeEvent(self, event):
# 通知线程停止
stop_event.set()
# 等待线程结束
self.thread.join()
return super().closeEvent(event)
使用qrc资源文件
更稳定,更适合qt程序,避免图片依赖
文件结构示例
project/
│
├─ icons/
│ ├─ app.png
│ ├─ open.png
│
├─ main.py
└─ resources.qrc
resources.qrc 文件内容如下:
<RCC>
<qresource prefix="/">
<file>icons/app.png</file>
<file>icons/open.png</file>
</qresource>
</RCC>
<RCC>:资源文件的根标签;<qresource>:定义一个资源集合;prefix="/"表示资源路径前缀;<file>:每一个被包含的文件路径。
如何使用
1.编译.qrc文件
Qt的资源文件必须编译成py文件才能在Python中使用
pyrcc5 resources.qrc -o resources_rc.py
或PySide2 版本:
pyside2-rcc resources.qrc -o resources_rc.py
2.在Python中导入使用
import sys
from PyQt5.QtWidgets import QApplication, QLabel
from PyQt5.QtGui import QPixmap
import resources_rc # 这一步是必须的!
app = QApplication(sys.argv)
label = QLabel()
label.setPixmap(QPixmap(":/icons/app.png")) # 使用冒号路径
label.show()
sys.exit(app.exec_())
选择列表元素切换页面
from PyQt5.QtWidgets import (
QApplication, QWidget, QListWidget, QStackedWidget,
QHBoxLayout, QLabel, QVBoxLayout, QListWidgetItem
)
from PyQt5.QtCore import Qt
import sys
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QListWidget + QStackedWidget 界面切换示例")
self.resize(700, 400)
# === 主布局 ===
main_layout = QHBoxLayout(self)
# 左侧菜单(QListWidget)
self.menu_list = QListWidget()
self.menu_list.setFixedWidth(150)
self.menu_list.setSpacing(5) # 项目间距
self.menu_list.setStyleSheet("""
QListWidget {
background-color: #f5f5f5;
border: none;
}
QListWidget::item {
height: 40px;
padding-left: 15px;
}
QListWidget::item:selected {
background-color: #0078d7;
color: white;
border-radius: 5px;
}
""")
# 添加菜单项
items = ["主页", "设置", "关于"]
for i, text in enumerate(items):
item = QListWidgetItem(text)
item.setTextAlignment(Qt.AlignVCenter)
self.menu_list.addItem(item)
# 右侧堆叠窗口(QStackedWidget)
self.stacked_widget = QStackedWidget()
# 创建三个页面
page_home = self.create_page("这是主页内容 😊")
page_settings = self.create_page("这是设置页面 ⚙️")
page_about = self.create_page("这是关于页面 📘")
# 添加页面进堆叠容器
self.stacked_widget.addWidget(page_home)
self.stacked_widget.addWidget(page_settings)
self.stacked_widget.addWidget(page_about)
# 把左右控件放进主布局
main_layout.addWidget(self.menu_list)
main_layout.addWidget(self.stacked_widget, 1)
# 默认选中第一个菜单项
self.menu_list.setCurrentRow(0)
# 连接信号:左侧菜单切换右侧页面
# 每当当前选中行发生变化时,Qt 会自动发出一个信号,并附带当前行号(一个 int 参数)。
self.menu_list.currentRowChanged.connect(self.stacked_widget.setCurrentIndex)
def create_page(self, text: str) -> QWidget:
"""创建一个简单页面"""
page = QWidget()
layout = QVBoxLayout(page)
label = QLabel(text)
label.setAlignment(Qt.AlignCenter)
label.setStyleSheet("font-size: 20px; color: #333;")
layout.addWidget(label)
return page
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

浙公网安备 33010602011771号