前面已经掌握了pyside6的基本框架和应用。从这一节开始详细展开学习pyside6的更多技术细节。
PySide6 中的交互类控件是用户与应用程序进行双向沟通的核心组件,涵盖按钮、输入框、选择器、滑块等,这类控件支持用户操作(点击、输入、选择等)并能触发响应逻辑。
这一节,学习按钮类。
按钮是最基础的交互控件,用于触发即时操作,PySide6 提供了多种功能化按钮变体。
1. QPushButton(普通按钮)
核心作用:响应点击事件,执行自定义逻辑(如提交表单、关闭窗口)。
关键特性:
- 支持文本 / 图标显示,可设置快捷键(如 &OK 对应 Alt+O);
- 可设置禁用 / 启用状态、默认按钮(回车触发)、复选模式(toggle)。
示例代码:
python
import sys
from PySide6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
class ButtonDemo(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle("QPushButton 示例")
layout = QVBoxLayout()
# 基础按钮
btn1 = QPushButton("普通按钮")
btn1.clicked.connect(self.on_btn1_clicked) # 绑定点击信号
# 带快捷键的按钮(Alt+S)
btn2 = QPushButton("&Save")
btn2.clicked.connect(lambda: print("保存操作"))
# 切换模式按钮(复选效果)
btn3 = QPushButton("切换按钮")
btn3.setCheckable(True)
btn3.toggled.connect(self.on_btn3_toggled)
# 禁用按钮
btn4 = QPushButton("禁用按钮")
btn4.setEnabled(False)
layout.addWidget(btn1)
layout.addWidget(btn2)
layout.addWidget(btn3)
layout.addWidget(btn4)
self.setLayout(layout)
def on_btn1_clicked(self):
print("普通按钮被点击")
def on_btn3_toggled(self, checked):
print(f"切换按钮状态: {'选中' if checked else '未选中'}")
if __name__ == "__main__":
app = QApplication(sys.argv)
demo = ButtonDemo()
demo.show()
sys.exit(app.exec())
2. QToolButton(工具按钮)
核心作用:常用于工具栏,支持图标优先显示、下拉菜单、箭头样式。
关键特性:
- 可设置 setToolButtonStyle() 控制图标 / 文本显示方式(如仅图标、文本在下);
- 支持关联下拉菜单(setMenu()),设置触发方式(点击 / 悬停)。
python
import sys
from PySide6.QtGui import QIcon
from PySide6.QtWidgets import (
QApplication, QMainWindow, QToolBar, QToolButton,
QWidget
)
class ToolButtonDemo(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("QToolButton 详解")
self.resize(400, 200)
# 1. 初始化工具栏
self.init_toolbar()
# 2. 初始化中心部件
self.init_centralWidget()
def init_toolbar(self):
# 创建工具栏
toolbar = QToolBar("主工具栏")
self.addToolBar(toolbar)
# 基础工具按钮(仅图标)
btn1 = QToolButton()
btn1.setIcon(QIcon("new.ico")) # 图标
btn1.setToolTip("新建文件") # 悬浮提示
btn1.clicked.connect(lambda: print("新建文件"))
toolbar.addWidget(btn1)
def init_centralWidget(self):
# 中心窗口布局
central = QWidget()
self.setCentralWidget(central)
if __name__ == "__main__":
app = QApplication(sys.argv)
demo = ToolButtonDemo()
demo.show()
sys.exit(app.exec())

3. QCheckBox(复选框)
核心作用:多选项选择(可多选),支持三态(选中 / 未选中 / 半选中,如子项部分选中)。
关键信号:stateChanged(int)(状态变化时触发,0 = 未选,1 = 半选,2 = 选中)。
python
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QCheckBox
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.cb = QCheckBox("三态复选框", self)
self.cb.setTristate(True) # 启用半选状态
# 状态变化(支持半选)
self.cb.stateChanged[int].connect(lambda state: print(f"状态:{state}"))
# 仅点击选中/未选
self.cb.clicked[bool].connect(lambda checked: print(f"选中:{checked}"))
self.cb.clicked.connect(lambda : print("被点击了"))
layout = QHBoxLayout()
layout.addWidget(self.cb)
self.setLayout(layout)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

4. QRadioButton(单选按钮)
核心作用:互斥选项选择(同一组内仅能选一个),需通过 QButtonGroup 管理互斥性。
示例:
python
from PySide6.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout, QButtonGroup, QRadioButton
from PySide6.QtCore import Slot, QMetaObject # 导入 slot 装饰器
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setLayout(QVBoxLayout())
self.btn_group = QButtonGroup()
radio1 = QRadioButton("选项1")
radio2 = QRadioButton("选项2")
radio3 = QRadioButton("选项3")
radio1.setChecked(True)
self.btn_group.addButton(radio1)
self.btn_group.addButton(radio2)
self.btn_group.addButton(radio3)
radio1.toggled.connect(self.on_radio_toggled)
radio2.toggled.connect(self.on_radio_toggled)
radio3.toggled.connect(self.on_radio_toggled)
self.layout().addWidget(radio1)
self.layout().addWidget(radio2)
self.layout().addWidget(radio3)
@Slot(bool)
def on_radio_toggled(self):
print(f"本次翻转的按钮是{self.sender().text()}: {self.sender().isChecked()}")
print(f"本次被选中的是:{self.btn_group.checkedButton().text()}")
if __name__ == "__main__":
app = QApplication([])
window = MyWindow()
window.show()
app.exec()

原生的单选按钮,选中标志图片和文字都很小,如果有需求,可以使用设置样式表,也就是setStyleSheet()的方法将其设置为自己的图片,同样的,它的字体也可以更改。
创建两个大小为40*40像素的图片文件,分别命名为Checked.png和unChecked.png:


然后:
python
import sys
from PySide6.QtWidgets import (
QApplication, QWidget, QRadioButton,
QVBoxLayout, QButtonGroup, QLabel
)
from PySide6.QtCore import Qt
class CustomRadioButtonDemo(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle("自定义QRadioButton(字体+图片)")
self.resize(400, 300)
# 1. 创建布局
layout = QVBoxLayout()
layout.setSpacing(20)
layout.setContentsMargins(40, 40, 40, 40)
# 2. 创建单选按钮组(保证互斥)
radio_group = QButtonGroup(self)
# 3. 创建自定义单选按钮
radio1 = QRadioButton("选项1(自定义样式)")
radio2 = QRadioButton("选项2(自定义样式)")
radio3 = QRadioButton("选项3(禁用状态)")
radio3.setEnabled(False) # 禁用按钮,测试禁用样式
# 4. 绑定按钮到组
radio_group.addButton(radio1)
radio_group.addButton(radio2)
radio_group.addButton(radio3)
# 5. 自定义样式(核心:字体 + 图片替换)
self.set_radio_style(radio1)
self.set_radio_style(radio2)
self.set_radio_style(radio3)
# 6. 信号绑定(可选,测试选中状态)
radio_group.buttonClicked.connect(
lambda btn: print(f"选中: {btn.text()}")
)
# 7. 添加到布局
layout.addWidget(radio1)
layout.addWidget(radio2)
layout.addWidget(radio3)
self.setLayout(layout)
def set_radio_style(self, radio_btn):
"""设置单选按钮的自定义样式(字体+图片)"""
# 替换为你的图片路径(绝对路径/相对路径/QRC路径)
unchecked_img = "unChecked.png" # 未选中图片
checked_img = "Checked.png" # 选中图片
# 样式表语法:CSS 风格,支持伪状态和子控件
style_sheet = f"""
/* 全局字体设置 */
QRadioButton {{
font-family: "Microsoft YaHei"; /* 字体 */
font-size: 16px; /* 字体大小 */
font-weight: 500; /* 字体粗细(400=常规,700=粗体) */
color: #333333; /* 字体颜色 */
spacing: 10px; /* 单选框与文本的间距 */
}}
/* 禁用状态的字体 */
QRadioButton:disabled {{
color: #999999; /* 禁用时字体变灰 */
}}
/* 单选框指示器(默认圆形)- 未选中状态 */
QRadioButton::indicator {{
width: 20px; /* 指示器宽度(匹配图片尺寸) */
height: 20px; /* 指示器高度 */
image: url({unchecked_img}); /* 未选中图片 */
}}
/* 选中状态的指示器 */
QRadioButton::indicator:checked {{
image: url({checked_img}); /* 选中图片 */
}}
/* 悬浮状态的指示器(可选) */
QRadioButton::indicator:hover {{
opacity: 0.9; /* 悬浮时轻微透明 */
}}
/* 禁用状态的指示器 */
QRadioButton::indicator:disabled {{
opacity: 0.5; /* 禁用时半透明 */
}}
"""
radio_btn.setStyleSheet(style_sheet)
if __name__ == "__main__":
app = QApplication(sys.argv)
demo = CustomRadioButtonDemo()
demo.show()
sys.exit(app.exec())
运行结果:

除了使用设置样式表,还可以使用重写绘制事件的方法(def paintEvent(self, event)
),来实现动态图片的显示,比如我们可以利用复选框(QCheckBox)或按压按钮(QPushButton),实现一个电气scada界面中常见的"带指示灯按钮":




python
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QCheckBox,
QVBoxLayout, QLabel, QPushButton)
from PySide6.QtCore import Qt, QSize
from PySide6.QtGui import QPixmap, QPainter, QMouseEvent
class IndicatorPushButton(QPushButton):
"""带指示灯的按钮"""
def __init__(self, parent=None):
super().__init__(parent)
self.setCheckable(True)
# 初始化图片路径(请替换为你的实际图片路径)
self.img_unchecked_not_pressed = "unChecked_notPressed.png"
self.img_unchecked_pressed = "unChecked_pressed.png"
self.img_checked_not_pressed = "checked_notPressed.png"
self.img_checked_pressed = "checked_pressed.png"
# 初始化状态变量
self.is_pressed = False # 记录是否被按压
# 设置按钮大小(根据你的图片尺寸调整)
self.setFixedSize(60, 60)
# 取消默认的勾选框样式
# self.setStyleSheet("QCheckBox { border: none; }")
def paintEvent(self, event):
"""重写绘制事件,根据状态绘制对应图片"""
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# 根据状态选择对应的图片
if self.isChecked():
img_path = self.img_checked_pressed if self.is_pressed else self.img_checked_not_pressed
else:
img_path = self.img_unchecked_pressed if self.is_pressed else self.img_unchecked_not_pressed
# 加载并绘制图片
pixmap = QPixmap(img_path)
if not pixmap.isNull():
# 缩放图片适配按钮大小(保持比例)
scaled_pixmap = pixmap.scaled(self.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
# 居中绘制
x = (self.width() - scaled_pixmap.width()) // 2
y = (self.height() - scaled_pixmap.height()) // 2
painter.drawPixmap(x, y, scaled_pixmap)
else:
# 图片加载失败时绘制默认提示
painter.drawText(self.rect(), Qt.AlignCenter, "图片加载失败")
def mousePressEvent(self, event):
"""鼠标按下事件:更新按压状态并重绘"""
if event.button() == Qt.LeftButton:
self.is_pressed = True
self.update() # 触发重绘
super().mousePressEvent(event)
def mouseReleaseEvent(self, event):
"""鼠标释放事件:更新按压状态并重绘"""
if event.button() == Qt.LeftButton:
self.is_pressed = False
self.update() # 触发重绘
super().mouseReleaseEvent(event)
def leaveEvent(self, event):
"""鼠标离开按钮时,重置按压状态(防止拖拽离开时状态异常)"""
self.is_pressed = False
self.update()
super().leaveEvent(event)
class DemoWindow(QWidget):
"""演示窗口"""
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
# 设置窗口属性
self.setWindowTitle("带指示灯的按钮")
self.resize(300, 200)
# 创建布局
layout = QVBoxLayout()
# 创建自定义按钮
self.push_btn = IndicatorPushButton()
# 连接状态变化信号
self.push_btn.clicked.connect(self.on_button_state_changed)
# 创建状态提示标签
self.status_label = QLabel("当前状态:off")
# 添加控件到布局
layout.addWidget(self.push_btn, alignment=Qt.AlignCenter)
layout.addWidget(self.status_label, alignment=Qt.AlignCenter)
# 设置布局
self.setLayout(layout)
def on_button_state_changed(self, state):
"""状态变化回调"""
# print(state)
if state:
self.status_label.setText("当前状态:on")
else:
self.status_label.setText("当前状态:off")
if __name__ == "__main__":
app = QApplication(sys.argv)
# 注意:请将图片路径替换为你的实际图片路径
# 建议将图片放在程序同目录下
window = DemoWindow()
window.show()
sys.exit(app.exec())
