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)

参数说明

  1. horizontalPolicy
  • 控制占位符在水平方向上的大小策略。
  • 类型为 QSizePolicy.Policy,常用的值包括:
    • QSizePolicy.Minimum:占位符的大小不能小于初始宽度。
    • QSizePolicy.Expanding:占位符可以扩展以填充可用空间。
    • QSizePolicy.Fixed:占位符的大小固定为初始宽度。
    • QSizePolicy.Preferred:占位符的大小优先使用初始宽度,但可以扩展。
  1. 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.实战技巧与性能优化

  1. 批量填充数据前关闭排序和信号:
table.setSortingEnabled(False)
table.blockSignals(True)
# 批量插入数据
table.blockSignals(False)
table.setSortingEnabled(True)
  1. 使用 setRowCount(n) 比循环插入更快。
  2. 大量数据建议使用 QTableView + QAbstractTableModel
  3. setCellWidget() 会降低性能,避免大量控件。
  4. 清空时用 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_())

布局

  1. 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)#设置布局中控件的间距

  2. 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)

对齐方式

  1. 水平对齐

    Qt.AlignLeft:左对齐。
    
    Qt.AlignRight:右对齐。
    
    Qt.AlignHCenter:水平居中对齐。
    
    Qt.AlignJustify:两端对齐。
    
  2. 垂直对齐

    Qt.AlignTop:顶部对齐。
    
    Qt.AlignBottom:底部对齐。
    
    Qt.AlignVCenter:垂直居中对齐。
    
  3. 组合对齐

    水平和垂直对齐可以组合使用,例如:

    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_())
posted @ 2026-07-02 17:56  畅畅c  阅读(0)  评论(0)    收藏  举报