第一章:容器组件专题
1. QWidget 基础与应用
QWidget 作为基类的特性
QWidget 是所有用户界面对象的根基,宛如一座空白的画布,为构建丰富多样的用户界面提供了基础。它是 PySide6 中各类组件的基类,具备了一些通用的属性和方法,为其他组件的扩展和定制提供了强大的支撑。
在 QWidget 中添加其他组件示例
它具备强大的包容性,能够作为一个空白的容器,方便开发者往其中添加各式各样的其他组件,从而根据具体需求打造出独一无二的界面布局。无论是简单的小型界面,还是复杂的大型应用程序界面,QWidget 都能发挥其不可或缺的作用。
简单示例
示例代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PySide6 QWidget示例
QWidget是所有用户界面对象的基类,可作为空白容器添加其他组件
"""
import sys
from PySide6.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout
from PySide6.QtCore import Qt
class SimpleWidget(QWidget):
def __init__(self):
super().__init__()
# 设置窗口标题和大小
self.setWindowTitle("QWidget示例")
self.resize(400, 300)
# 创建组件
self.label = QLabel("这是一个基本的QWidget容器")
self.label.setAlignment(Qt.AlignCenter)
self.button = QPushButton("点击我")
self.button.clicked.connect(self.on_button_clicked)
# 创建布局并添加组件
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.button)
# 设置布局
self.setLayout(layout)
def on_button_clicked(self):
self.label.setText("按钮被点击了!")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = SimpleWidget()
window.show()
sys.exit(app.exec())
示例效果
2. QMainWindow 构建主窗口
菜单栏、工具栏和状态栏的设置
QMainWindow 专门用于创建应用程序的主窗口,是构建应用程序主界面的核心组件。它就像一个功能齐全的指挥中心,内置了菜单栏、工具栏和状态栏等重要元素。菜单栏可用于提供各种操作选项,方便用户快速访问不同功能;工具栏则以简洁直观的图标形式,让常用操作触手可及;状态栏则能实时显示应用程序的相关状态信息,为用户带来更加便捷和高效的使用体验。通过合理设置这些元素,可以让主窗口的功能更加丰富和易用。
主窗口布局管理
在使用 QMainWindow 时,合理的布局管理至关重要。它可以帮助我们将各个组件有序地排列在窗口中,提高界面的美观度和易用性。可以使用不同的布局管理器,如 QVBoxLayout、QHBoxLayout 等,来实现不同的布局效果。
简单示例
示例代码
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QTextEdit, QMenuBar, QToolBar, QStatusBar
class MainWindowDemo(QMainWindow):
def __init__(self):
super().__init__()
# 设置窗口标题和大小
self.setWindowTitle("QMainWindow示例")
self.resize(600, 400)
# 创建中央部件 - 文本编辑器
self.text_edit = QTextEdit()
self.setCentralWidget(self.text_edit)
# 创建菜单栏
menubar = self.menuBar()
file_menu = menubar.addMenu("文件")
edit_menu = menubar.addMenu("编辑")
# 创建工具栏
toolbar = QToolBar("主工具栏")
self.addToolBar(toolbar)
# 创建状态栏
statusbar = QStatusBar()
self.setStatusBar(statusbar)
statusbar.showMessage("就绪")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindowDemo()
window.show()
sys.exit(app.exec())
示例效果

3. QDialog 对话框设计
模态与非模态对话框的使用场景
QDialog 主要用于创建对话框,是实现简单用户交互的得力工具。对话框就像是与用户进行短暂交流的窗口,根据实际需求,它具有模态和非模态两种显示方式。模态对话框会阻止用户与应用程序的其他部分进行交互,直到对话框被关闭,适用于需要用户立即做出响应的场景,如确认删除操作等;而非模态对话框则允许用户在对话框打开的同时与应用程序的其他部分继续交互,提供了更大的操作灵活性,例如查看帮助信息时。
对话框中的用户交互处理
在对话框中,需要处理用户的各种输入和操作。可以通过信号与槽机制来实现用户交互的响应,例如当用户点击对话框中的确认按钮时,执行相应的操作。
简单示例
示例代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PySide6 QDialog示例
QDialog创建对话框,用于简单的用户交互,有模态和非模态显示方式
"""
import sys
from PySide6.QtWidgets import (QApplication, QDialog, QVBoxLayout, QHBoxLayout,
QPushButton, QLabel, QLineEdit, QDialogButtonBox,
QMessageBox)
from PySide6.QtCore import Qt
class CustomDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
# 设置窗口标题和大小
self.setWindowTitle("自定义对话框")
self.resize(400, 200)
# 创建布局
layout = QVBoxLayout()
# 添加标签和输入框
self.name_label = QLabel("姓名:")
self.name_input = QLineEdit()
self.email_label = QLabel("邮箱:")
self.email_input = QLineEdit()
# 添加到布局
form_layout = QVBoxLayout()
form_layout.addWidget(self.name_label)
form_layout.addWidget(self.name_input)
form_layout.addWidget(self.email_label)
form_layout.addWidget(self.email_input)
layout.addLayout(form_layout)
# 添加按钮
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
layout.addWidget(button_box)
self.setLayout(layout)
def get_inputs(self):
return {
"name": self.name_input.text(),
"email": self.email_input.text()
}
class MainWindow(QDialog):
def __init__(self):
super().__init__()
# 设置窗口标题和大小
self.setWindowTitle("QDialog示例")
self.resize(500, 300)
# 创建布局
layout = QVBoxLayout()
# 添加标签
self.info_label = QLabel("这是一个QDialog示例,演示模态和非模态对话框")
self.info_label.setAlignment(Qt.AlignCenter)
layout.addWidget(self.info_label)
# 添加结果标签
self.result_label = QLabel("对话框结果将显示在这里")
self.result_label.setAlignment(Qt.AlignCenter)
layout.addWidget(self.result_label)
# 创建按钮布局
button_layout = QHBoxLayout()
# 添加模态对话框按钮
self.modal_button = QPushButton("打开模态对话框")
self.modal_button.clicked.connect(self.open_modal_dialog)
button_layout.addWidget(self.modal_button)
# 添加非模态对话框按钮
self.non_modal_button = QPushButton("打开非模态对话框")
self.non_modal_button.clicked.connect(self.open_non_modal_dialog)
button_layout.addWidget(self.non_modal_button)
# 添加消息框按钮
self.message_box_button = QPushButton("打开消息框")
self.message_box_button.clicked.connect(self.open_message_box)
button_layout.addWidget(self.message_box_button)
layout.addLayout(button_layout)
self.setLayout(layout)
# 保存非模态对话框的引用
self.non_modal_dialog = None
def open_modal_dialog(self):
"""打开模态对话框"""
dialog = CustomDialog(self)
# 模态对话框会阻塞主窗口,直到对话框关闭
result = dialog.exec()
if result == QDialog.Accepted:
inputs = dialog.get_inputs()
self.result_label.setText(f"模态对话框结果: 姓名={inputs['name']}, 邮箱={inputs['email']}")
else:
self.result_label.setText("模态对话框被取消")
def open_non_modal_dialog(self):
"""打开非模态对话框"""
# 创建非模态对话框
self.non_modal_dialog = CustomDialog(self)
# 连接信号
self.non_modal_dialog.accepted.connect(self.on_non_modal_accepted)
self.non_modal_dialog.rejected.connect(self.on_non_modal_rejected)
# 非模态显示,不会阻塞主窗口
self.non_modal_dialog.show()
def on_non_modal_accepted(self):
"""非模态对话框接受时的处理"""
if self.non_modal_dialog:
inputs = self.non_modal_dialog.get_inputs()
self.result_label.setText(f"非模态对话框结果: 姓名={inputs['name']}, 邮箱={inputs['email']}")
def on_non_modal_rejected(self):
"""非模态对话框拒绝时的处理"""
self.result_label.setText("非模态对话框被取消")
def open_message_box(self):
"""打开消息框"""
# QMessageBox是QDialog的子类,用于显示消息
msg_box = QMessageBox(self)
msg_box.setWindowTitle("消息框")
msg_box.setText("这是一个消息框示例")
msg_box.setInformativeText("你想要继续吗?")
msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
msg_box.setDefaultButton(QMessageBox.Yes)
# 显示消息框并获取结果
result = msg_box.exec()
# 处理结果
if result == QMessageBox.Yes:
self.result_label.setText("消息框结果: 是")
elif result == QMessageBox.No:
self.result_label.setText("消息框结果: 否")
else:
self.result_label.setText("消息框结果: 取消")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
示例效果
- 默认窗口

- 打开模态对话框

-
打开非模态对话框

-
打开消息框

4. QFrame 分组与分隔
利用 QFrame 美化界面布局
QFrame 是一个带有边框的容器,其作用类似于一个精致的相框,能够对其他组件进行有效的分组和分隔。通过使用 QFrame,可以将界面中的相关组件划分成不同的区域,使界面布局更加清晰明了,增强了界面的层次感和可读性。同时,QFrame 还支持多种边框样式的设置,能够满足不同的设计需求,为界面美化提供了更多的可能性。
不同边框样式的 QFrame 应用
可以根据实际需求为 QFrame 设置不同的边框样式,如实线边框、虚线边框等,以达到不同的视觉效果。不同的边框样式可以用于区分不同的功能区域,使界面更加直观和易于理解。
简单示例
示例代码
import sys
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QFrame, QLabel
class FrameDemo(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QFrame示例")
self.resize(400, 300)
layout = QVBoxLayout()
# 创建不同样式的QFrame
frame1 = QFrame()
frame1.setFrameStyle(QFrame.Box | QFrame.Plain) # 普通方框
frame1.setLineWidth(2)
label1 = QLabel("普通方框 (QFrame.Box)")
frame1.setLayout(QVBoxLayout())
frame1.layout().addWidget(label1)
frame2 = QFrame()
frame2.setFrameStyle(QFrame.Panel | QFrame.Raised) # 凸起面板
frame2.setLineWidth(2)
label2 = QLabel("凸起面板 (QFrame.Panel | QFrame.Raised)")
frame2.setLayout(QVBoxLayout())
frame2.layout().addWidget(label2)
frame3 = QFrame()
frame3.setFrameStyle(QFrame.WinPanel | QFrame.Sunken) # 凹陷面板
frame3.setLineWidth(2)
label3 = QLabel("凹陷面板 (QFrame.WinPanel | QFrame.Sunken)")
frame3.setLayout(QVBoxLayout())
frame3.layout().addWidget(label3)
frame4 = QFrame()
frame4.setFrameStyle(QFrame.HLine | QFrame.Sunken) # 水平线
frame4.setLineWidth(2)
# 添加到布局
layout.addWidget(frame1)
layout.addWidget(frame2)
layout.addWidget(frame3)
layout.addWidget(QLabel("水平分隔线:"))
layout.addWidget(frame4)
self.setLayout(layout)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = FrameDemo()
window.show()
sys.exit(app.exec())
示例效果

5. QGroupBox 增强可读性
为组件分组添加标题
QGroupBox 为一组相关的组件提供了一个带有标题的框架,就像一个分类文件夹,将相关的内容有序地组织在一起。这个标题就像是文件夹的标签,能够直观地告诉用户该组组件的功能或用途,大大增强了界面的可读性。
分组组件的交互设计
在分组组件时,需要考虑组件之间的交互关系。例如,当一个组件的状态发生变化时,可能会影响到同一组内其他组件的显示或功能。可以通过信号与槽机制来实现组件之间的交互,提高用户体验。
简单示例
示例代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PySide6 QGroupBox示例
QGroupBox为一组相关的组件提供一个带有标题的框架,增强界面的可读性
"""
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QGroupBox, QVBoxLayout,
QHBoxLayout, QLabel, QPushButton, QRadioButton,
QCheckBox, QLineEdit, QComboBox, QSpinBox)
from PySide6.QtCore import Qt
class GroupBoxExample(QWidget):
def __init__(self):
super().__init__()
# 设置窗口标题和大小
self.setWindowTitle("QGroupBox示例")
self.resize(700, 500)
# 创建主布局
main_layout = QVBoxLayout()
# 创建标题标签
title_label = QLabel("QGroupBox 分组示例")
title_label.setAlignment(Qt.AlignCenter)
title_label.setStyleSheet("font-size: 16px; font-weight: bold;")
main_layout.addWidget(title_label)
# 创建水平布局来放置不同的组
top_layout = QHBoxLayout()
# 创建基本信息组
self.create_basic_info_group(top_layout)
# 创建单选按钮组
self.create_radio_group(top_layout)
main_layout.addLayout(top_layout)
# 创建第二行布局
middle_layout = QHBoxLayout()
# 创建复选框组
self.create_checkbox_group(middle_layout)
# 创建下拉选择组
self.create_dropdown_group(middle_layout)
main_layout.addLayout(middle_layout)
# 创建第三行布局
bottom_layout = QHBoxLayout()
# 创建可折叠组
self.create_collapsible_group(bottom_layout)
# 创建嵌套组
self.create_nested_group(bottom_layout)
main_layout.addLayout(bottom_layout)
# 创建结果显示区域
self.result_label = QLabel("操作结果将显示在这里")
self.result_label.setAlignment(Qt.AlignCenter)
self.result_label.setStyleSheet("background-color: #f0f0f0; padding: 10px;")
main_layout.addWidget(self.result_label)
# 设置主布局
self.setLayout(main_layout)
def create_basic_info_group(self, parent_layout):
"""创建基本信息组"""
group_box = QGroupBox("基本信息")
group_box.setStyleSheet("QGroupBox { font-weight: bold; }")
# 创建布局
layout = QVBoxLayout()
# 添加姓名输入
name_layout = QHBoxLayout()
name_label = QLabel("姓名:")
self.name_input = QLineEdit()
name_layout.addWidget(name_label)
name_layout.addWidget(self.name_input)
layout.addLayout(name_layout)
# 添加年龄输入
age_layout = QHBoxLayout()
age_label = QLabel("年龄:")
self.age_input = QSpinBox()
self.age_input.setRange(1, 120)
self.age_input.setValue(25)
age_layout.addWidget(age_label)
age_layout.addWidget(self.age_input)
layout.addLayout(age_layout)
# 添加提交按钮
submit_button = QPushButton("提交信息")
submit_button.clicked.connect(self.submit_basic_info)
layout.addWidget(submit_button)
group_box.setLayout(layout)
parent_layout.addWidget(group_box)
def create_radio_group(self, parent_layout):
"""创建单选按钮组"""
group_box = QGroupBox("选择性别")
group_box.setStyleSheet("QGroupBox { font-weight: bold; }")
# 设置为单选模式
group_box.setCheckable(False)
# 创建布局
layout = QVBoxLayout()
# 添加单选按钮
self.male_radio = QRadioButton("男")
self.female_radio = QRadioButton("女")
self.other_radio = QRadioButton("其他")
# 默认选中第一个
self.male_radio.setChecked(True)
# 连接信号
self.male_radio.toggled.connect(self.on_gender_changed)
self.female_radio.toggled.connect(self.on_gender_changed)
self.other_radio.toggled.connect(self.on_gender_changed)
layout.addWidget(self.male_radio)
layout.addWidget(self.female_radio)
layout.addWidget(self.other_radio)
group_box.setLayout(layout)
parent_layout.addWidget(group_box)
def create_checkbox_group(self, parent_layout):
"""创建复选框组"""
group_box = QGroupBox("选择兴趣爱好")
group_box.setStyleSheet("QGroupBox { font-weight: bold; }")
# 创建布局
layout = QVBoxLayout()
# 添加复选框
self.reading_checkbox = QCheckBox("阅读")
self.sports_checkbox = QCheckBox("运动")
self.music_checkbox = QCheckBox("音乐")
self.travel_checkbox = QCheckBox("旅行")
# 连接信号
self.reading_checkbox.stateChanged.connect(self.on_hobby_changed)
self.sports_checkbox.stateChanged.connect(self.on_hobby_changed)
self.music_checkbox.stateChanged.connect(self.on_hobby_changed)
self.travel_checkbox.stateChanged.connect(self.on_hobby_changed)
layout.addWidget(self.reading_checkbox)
layout.addWidget(self.sports_checkbox)
layout.addWidget(self.music_checkbox)
layout.addWidget(self.travel_checkbox)
group_box.setLayout(layout)
parent_layout.addWidget(group_box)
def create_dropdown_group(self, parent_layout):
"""创建下拉选择组"""
group_box = QGroupBox("选择城市")
group_box.setStyleSheet("QGroupBox { font-weight: bold; }")
# 创建布局
layout = QVBoxLayout()
# 添加下拉框
self.city_combo = QComboBox()
self.city_combo.addItems(["北京", "上海", "广州", "深圳", "杭州", "成都", "重庆"])
self.city_combo.currentTextChanged.connect(self.on_city_changed)
layout.addWidget(QLabel("请选择城市:"))
layout.addWidget(self.city_combo)
# 添加一些空间
layout.addStretch()
group_box.setLayout(layout)
parent_layout.addWidget(group_box)
def create_collapsible_group(self, parent_layout):
"""创建可折叠组"""
group_box = QGroupBox("高级设置 (可折叠)")
group_box.setStyleSheet("QGroupBox { font-weight: bold; }")
# 设置为可折叠
group_box.setCheckable(True)
group_box.setChecked(False) # 默认折叠
# 连接信号
group_box.toggled.connect(self.on_advanced_toggled)
# 创建布局
layout = QVBoxLayout()
# 添加一些设置选项
layout.addWidget(QLabel("这些是高级设置选项"))
layout.addWidget(QCheckBox("启用调试模式"))
layout.addWidget(QCheckBox("显示隐藏文件"))
layout.addWidget(QCheckBox("自动保存"))
group_box.setLayout(layout)
parent_layout.addWidget(group_box)
def create_nested_group(self, parent_layout):
"""创建嵌套组"""
group_box = QGroupBox("嵌套分组示例")
group_box.setStyleSheet("QGroupBox { font-weight: bold; }")
# 创建布局
layout = QVBoxLayout()
# 创建嵌套的组框
nested_group = QGroupBox("内部分组")
nested_layout = QVBoxLayout()
nested_layout.addWidget(QLabel("这是嵌套在另一个GroupBox中的GroupBox"))
nested_layout.addWidget(QPushButton("内部按钮"))
nested_group.setLayout(nested_layout)
layout.addWidget(nested_group)
# 添加一个按钮
layout.addWidget(QPushButton("外部按钮"))
group_box.setLayout(layout)
parent_layout.addWidget(group_box)
def submit_basic_info(self):
"""提交基本信息"""
name = self.name_input.text()
age = self.age_input.value()
self.result_label.setText(f"提交的基本信息: 姓名={name}, 年龄={age}")
def on_gender_changed(self):
"""性别选择改变时的处理"""
if self.male_radio.isChecked():
gender = "男"
elif self.female_radio.isChecked():
gender = "女"
else:
gender = "其他"
self.result_label.setText(f"选择的性别: {gender}")
def on_hobby_changed(self):
"""兴趣爱好选择改变时的处理"""
hobbies = []
if self.reading_checkbox.isChecked():
hobbies.append("阅读")
if self.sports_checkbox.isChecked():
hobbies.append("运动")
if self.music_checkbox.isChecked():
hobbies.append("音乐")
if self.travel_checkbox.isChecked():
hobbies.append("旅行")
if hobbies:
self.result_label.setText(f"选择的兴趣爱好: {', '.join(hobbies)}")
else:
self.result_label.setText("未选择任何兴趣爱好")
def on_city_changed(self, city):
"""城市选择改变时的处理"""
self.result_label.setText(f"选择的城市: {city}")
def on_advanced_toggled(self, checked):
"""高级设置组展开/折叠时的处理"""
if checked:
self.result_label.setText("高级设置已展开")
else:
self.result_label.setText("高级设置已折叠")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = GroupBoxExample()
window.show()
sys.exit(app.exec())
示例效果

6. QTabWidget 选项卡界面实现
多页面切换的流畅体验
QTabWidget 提供了一种非常实用的选项卡界面,它就像一本多页的书籍,用户可以通过点击不同的选项卡轻松地在多个页面之间进行切换。这种界面设计方式能够有效地节省界面空间,将大量的内容以分页的形式进行展示,让用户能够更加方便地浏览和管理不同的信息。为了实现流畅的切换体验,可以设置合适的动画效果和切换速度。
选项卡的样式定制
可以对 QTabWidget 的选项卡样式进行定制,如更改选项卡的颜色、字体、大小等,以满足不同的设计需求。通过样式定制,可以使选项卡界面更加美观和符合应用程序的整体风格。
简单示例
示例代码
import sys
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QTabWidget, QLabel, QPushButton, QTextEdit
class TabWidgetDemo(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QTabWidget示例")
self.resize(500, 400)
# 创建主布局
layout = QVBoxLayout()
# 创建标签页组件
tab_widget = QTabWidget()
# 创建第一个标签页
tab1 = QWidget()
tab1_layout = QVBoxLayout()
tab1_layout.addWidget(QLabel("这是第一个标签页"))
tab1_layout.addWidget(QPushButton("按钮1"))
tab1.setLayout(tab1_layout)
# 创建第二个标签页
tab2 = QWidget()
tab2_layout = QVBoxLayout()
tab2_layout.addWidget(QLabel("这是第二个标签页"))
text_edit = QTextEdit()
text_edit.setPlainText("在这里输入文本...")
tab2_layout.addWidget(text_edit)
tab2.setLayout(tab2_layout)
# 创建第三个标签页
tab3 = QWidget()
tab3_layout = QVBoxLayout()
tab3_layout.addWidget(QLabel("这是第三个标签页"))
tab3_layout.addWidget(QPushButton("按钮2"))
tab3_layout.addWidget(QPushButton("按钮3"))
tab3.setLayout(tab3_layout)
# 添加标签页
tab_widget.addTab(tab1, "基本信息")
tab_widget.addTab(tab2, "文本编辑")
tab_widget.addTab(tab3, "操作面板")
# 设置标签页可关闭
tab_widget.setTabsClosable(True)
tab_widget.tabCloseRequested.connect(lambda index: tab_widget.removeTab(index))
# 添加到主布局
layout.addWidget(tab_widget)
self.setLayout(layout)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TabWidgetDemo()
window.show()
sys.exit(app.exec())
示例效果

7. QSplitter 动态调整布局
拖动分隔条调整子组件大小
QSplitter 赋予了用户一种动态调整界面布局的能力,它允许用户通过拖动分隔条来灵活地调整子组件的大小。就像一个可以自由调节的隔板,用户可以根据自己的需求和实际情况,实时改变各个组件所占的空间比例,以达到最佳的显示效果。
响应式布局中的 QSplitter 应用
在响应式布局中,QSplitter 可以发挥重要作用。当窗口大小发生变化时,通过合理设置 QSplitter 的属性,可以使子组件自动调整大小,以适应不同的屏幕尺寸和布局需求。
简单示例
示例代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PySide6 QSplitter示例
QSplitter允许用户通过拖动分隔条来调整子组件的大小
"""
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QSplitter, QVBoxLayout,
QHBoxLayout, QLabel, QPushButton, QTextEdit,
QListWidget, QTreeWidget, QTreeWidgetItem,
QFrame, QGroupBox, QRadioButton)
from PySide6.QtCore import Qt, QSize
from PySide6.QtGui import QColor
class SplitterExample(QWidget):
def __init__(self):
super().__init__()
# 设置窗口标题和大小
self.setWindowTitle("QSplitter示例")
self.resize(800, 600)
# 创建主布局
main_layout = QVBoxLayout()
# 创建标题标签
title_label = QLabel("QSplitter 分割器示例")
title_label.setAlignment(Qt.AlignCenter)
title_label.setStyleSheet("font-size: 16px; font-weight: bold;")
main_layout.addWidget(title_label)
# 创建水平分割器示例
horizontal_label = QLabel("水平分割器示例")
horizontal_label.setAlignment(Qt.AlignCenter)
main_layout.addWidget(horizontal_label)
# 创建水平分割器
h_splitter = self.create_horizontal_splitter()
main_layout.addWidget(h_splitter)
# 创建垂直分割器示例
vertical_label = QLabel("垂直分割器示例")
vertical_label.setAlignment(Qt.AlignCenter)
main_layout.addWidget(vertical_label)
# 创建垂直分割器
v_splitter = self.create_vertical_splitter()
main_layout.addWidget(v_splitter)
# 创建嵌套分割器示例
nested_label = QLabel("嵌套分割器示例 (类似IDE布局)")
nested_label.setAlignment(Qt.AlignCenter)
main_layout.addWidget(nested_label)
# 创建嵌套分割器
nested_splitter = self.create_nested_splitter()
main_layout.addWidget(nested_splitter)
# 创建控制按钮布局
control_layout = QHBoxLayout()
# 添加重置按钮
reset_button = QPushButton("重置分割器")
reset_button.clicked.connect(self.reset_splitters)
control_layout.addWidget(reset_button)
# 添加切换方向按钮
self.toggle_direction_button = QPushButton("切换方向 (水平/垂直)")
self.toggle_direction_button.clicked.connect(self.toggle_direction)
control_layout.addWidget(self.toggle_direction_button)
main_layout.addLayout(control_layout)
# 创建状态标签
self.status_label = QLabel("拖动分隔条来调整各部分的大小")
self.status_label.setAlignment(Qt.AlignCenter)
self.status_label.setStyleSheet("background-color: #f0f0f0; padding: 5px;")
main_layout.addWidget(self.status_label)
# 保存分割器引用
self.h_splitter = h_splitter
self.v_splitter = v_splitter
self.nested_splitter = nested_splitter
# 设置主布局
self.setLayout(main_layout)
def create_horizontal_splitter(self):
"""创建水平分割器"""
splitter = QSplitter(Qt.Horizontal)
# 左侧部分
left_widget = QListWidget()
left_widget.addItems([f"项目 {i+1}" for i in range(10)])
# 中间部分
middle_widget = QTextEdit()
middle_widget.setPlaceholderText("这是中间部分,可以输入文本...")
# 右侧部分
right_widget = QGroupBox("选项")
right_layout = QVBoxLayout()
right_layout.addWidget(QRadioButton("选项 1"))
right_layout.addWidget(QRadioButton("选项 2"))
right_layout.addWidget(QRadioButton("选项 3"))
right_widget.setLayout(right_layout)
# 添加部件到分割器
splitter.addWidget(left_widget)
splitter.addWidget(middle_widget)
splitter.addWidget(right_widget)
# 设置初始大小
splitter.setSizes([200, 400, 200])
# 设置处理方式
splitter.setHandleWidth(8)
splitter.setChildrenCollapsible(False) # 防止子部件被完全折叠
return splitter
def create_vertical_splitter(self):
"""创建垂直分割器"""
splitter = QSplitter(Qt.Vertical)
# 上部分
top_widget = QTextEdit()
top_widget.setPlaceholderText("这是上部分,可以输入文本...")
# 下部分
bottom_widget = QTextEdit()
bottom_widget.setPlaceholderText("这是下部分,可以输入文本...")
bottom_widget.setStyleSheet("background-color: #f5f5f5;")
# 添加部件到分割器
splitter.addWidget(top_widget)
splitter.addWidget(bottom_widget)
# 设置初始大小
splitter.setSizes([200, 100])
# 设置处理方式
splitter.setHandleWidth(8)
return splitter
def create_nested_splitter(self):
"""创建嵌套分割器 (类似IDE布局)"""
# 创建主分割器 (水平)
main_splitter = QSplitter(Qt.Horizontal)
# 创建左侧部分 (项目浏览器)
project_tree = QTreeWidget()
project_tree.setHeaderLabel("项目结构")
# 添加一些项目
root = QTreeWidgetItem(project_tree, ["我的项目"])
src_folder = QTreeWidgetItem(root, ["源代码"])
QTreeWidgetItem(src_folder, ["main.py"])
QTreeWidgetItem(src_folder, ["utils.py"])
QTreeWidgetItem(src_folder, ["models.py"])
resources_folder = QTreeWidgetItem(root, ["资源"])
QTreeWidgetItem(resources_folder, ["images"])
QTreeWidgetItem(resources_folder, ["data.json"])
project_tree.expandAll()
# 创建右侧分割器 (垂直)
right_splitter = QSplitter(Qt.Vertical)
# 创建编辑器部分
editor = QTextEdit()
editor.setPlaceholderText("# 这是代码编辑器区域\n\ndef main():\n print('Hello, QSplitter!')\n\nif __name__ == '__main__':\n main()")
# 创建输出/终端部分
output = QTextEdit()
output.setPlaceholderText("这是输出/终端区域...")
output.setStyleSheet("background-color: #2b2b2b; color: #f0f0f0;")
# 添加部件到右侧分割器
right_splitter.addWidget(editor)
right_splitter.addWidget(output)
right_splitter.setSizes([400, 200])
# 添加部件到主分割器
main_splitter.addWidget(project_tree)
main_splitter.addWidget(right_splitter)
main_splitter.setSizes([200, 600])
# 设置处理方式
main_splitter.setHandleWidth(8)
right_splitter.setHandleWidth(8)
return main_splitter
def reset_splitters(self):
"""重置所有分割器的大小"""
# 重置水平分割器
self.h_splitter.setSizes([200, 400, 200])
# 重置垂直分割器
self.v_splitter.setSizes([200, 100])
# 重置嵌套分割器
self.nested_splitter.setSizes([200, 600])
# 获取嵌套分割器的右侧部分 (也是一个分割器)
right_splitter = self.nested_splitter.widget(1)
if isinstance(right_splitter, QSplitter):
right_splitter.setSizes([400, 200])
self.status_label.setText("分割器已重置")
def toggle_direction(self):
"""切换水平分割器的方向"""
# 获取当前方向
current_orientation = self.h_splitter.orientation()
# 切换方向
if current_orientation == Qt.Horizontal:
self.h_splitter.setOrientation(Qt.Vertical)
self.status_label.setText("水平分割器方向: 垂直")
else:
self.h_splitter.setOrientation(Qt.Horizontal)
self.status_label.setText("水平分割器方向: 水平")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = SplitterExample()
window.show()
sys.exit(app.exec())
示例效果

8. QStackedWidget 页面切换
隐藏与显示子组件
QStackedWidget 就像是一个神奇的魔术盒,一次只显示一个子组件。用户可以在不同的页面之间进行切换,就像从魔术盒中挑选不同的物品一样。通过隐藏和显示子组件的方式,实现页面的切换效果。
页面切换的动画效果
为了增强用户体验,可以为 QStackedWidget 的页面切换添加动画效果,如淡入淡出、滑动等。这样可以使页面切换更加平滑和自然,给用户带来更好的视觉感受。
简单示例
示例代码
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout,
QPushButton, QLabel, QStackedWidget)
class StackedWidgetDemo(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QStackedWidget示例")
self.resize(400, 300)
# 主布局
main_layout = QVBoxLayout()
# 创建堆叠组件
self.stacked_widget = QStackedWidget()
# 创建3个页面
page1 = QWidget()
page1_layout = QVBoxLayout()
page1_layout.addWidget(QLabel("这是第一页"))
page1.setLayout(page1_layout)
page2 = QWidget()
page2_layout = QVBoxLayout()
page2_layout.addWidget(QLabel("这是第二页"))
page2.setLayout(page2_layout)
page3 = QWidget()
page3_layout = QVBoxLayout()
page3_layout.addWidget(QLabel("这是第三页"))
page3.setLayout(page3_layout)
# 添加页面到堆叠组件
self.stacked_widget.addWidget(page1)
self.stacked_widget.addWidget(page2)
self.stacked_widget.addWidget(page3)
# 创建控制按钮
btn_prev = QPushButton("上一页")
btn_prev.clicked.connect(self.prev_page)
btn_next = QPushButton("下一页")
btn_next.clicked.connect(self.next_page)
# 当前页标签
self.page_label = QLabel(f"当前页: 1/3")
# 添加到主布局
main_layout.addWidget(self.stacked_widget)
main_layout.addWidget(self.page_label)
main_layout.addWidget(btn_prev)
main_layout.addWidget(btn_next)
self.setLayout(main_layout)
def prev_page(self):
current = self.stacked_widget.currentIndex()
if current > 0:
self.stacked_widget.setCurrentIndex(current - 1)
self.page_label.setText(f"当前页: {current}/3")
def next_page(self):
current = self.stacked_widget.currentIndex()
if current < self.stacked_widget.count() - 1:
self.stacked_widget.setCurrentIndex(current + 1)
self.page_label.setText(f"当前页: {current + 2}/3")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = StackedWidgetDemo()
window.show()
sys.exit(app.exec())
示例效果


1367

被折叠的 条评论
为什么被折叠?



