PySide6从0开始学习的笔记(二) 控件(Widget)之容器类控件

一、控件(Widget)基本概念

        控件(Widget)本质是 图形界面(GUI)里的 “基础功能组件” —— 就像搭界面的 “乐高积木”,是用户能看见、能操作(或仅展示)的最小单元,不用懂 Qt 底层,记住 3 个核心点即可:

1. 控件的核心作用:“承上启下”

  • 对用户:提供交互入口(比如点按钮、输文字)或信息展示(比如看文本、图片);
  • 对程序:接收用户操作(比如点击、输入),或呈现程序处理结果(比如显示计算结果)。

2. 常见控件类型

  • 容器类:窗口(Window,最外层 “大容器”)、面板(Widget,把多个小控件归为一组等)。
  • 交互类:按钮(Button,点一下触发功能)、输入框(Line Edit,输文字 / 数字)、复选框(CheckBox,选 / 不选)、下拉菜单(ComboBox,选列表里的选项)等;
  • 展示类:标签(Label,显示文字 / 图片,不能改)、文本框(Text Edit,显示多行文字)、进度条(Progress Bar,展示加载 / 处理进度);

3. 控件的关键特性

  • 有 “属性”:比如按钮的文字、大小、颜色,输入框的默认值、是否可编辑;
  • 能 “响应事件”:用户操作会触发反应(比如点按钮→程序执行某个功能,输文字→程序接收输入内容);
  • 可 “组合嵌套”:比如把按钮、输入框放进一个面板,再把面板放进窗口,搭出复杂界面。

    二、容器类控件详解

            PySide6 中的容器类控件是用于组织、管理其他子控件的核心组件,它们不仅能承载多个控件,还提供布局管理、分组显示、页面切换等功能。

    • 容器类控件核心分类

            PySide6 的容器控件主要分为两类:

            基础布局容器:以布局管理为核心(如 QWidget、QFrame);

            功能型容器:提供分组、分页、滚动等附加功能(如 QGroupBox、QTabWidget、QScrollArea 等)。


    • QWidget(基础万能容器)

            QWidget 是所有 PySide6 控件的基类,本身也是最基础的容器 —— 任何 QWidget 实例都可以作为父控件,承载其他子控件,并通过布局管理器组织子控件的位置。                

    • 核心特性:
    1. 纯空白,可自定义背景、边框等;
    2. 支持布局嵌套;
    3. 可作为独立窗口或子容器使用。

    import sys
    
    from PySide6.QtWidgets import QApplication, QWidget
    
    
    # 定义一个父容器类,作为主窗口
    class MainWindow(QWidget):
      def __init__(self):
        super().__init__()
        self.setWindowTitle("QWidget 基础容器示例")
        self.setStyleSheet("background-color: green;")  # 设置容器的显示样式,方便观察
        self.resize(300, 200)
    
        # 创建 QWidget 作为子容器
        son_container = QWidget(self)
        son_container.setGeometry(10, 10, 280, 180)  # 设置子容器的几何特征,位置为 (10, 10),大小为 (280, 180)
        son_container.setStyleSheet("background-color: red")  # 设置容器的显示样式,方便观察
    
    
    if __name__ == "__main__":
      app = QApplication(sys.argv)  # 创建 QApplication 对象
      main_window = MainWindow()  # 创建 MainWindow 实例对象
      main_window.show()   # 显示窗口
      sys.exit(app.exec())   # 退出应用程序

            

            在上面这个实例中,有两个QWidget容器,背景色为绿色的是主窗口main_window,背景色为红色的是主窗口的子容器son_container。

    继续,在子容器son_container中放置控件:

    import sys
    
    from PySide6.QtWidgets import QApplication, QWidget, QPushButton
    
    
    # 定义一个父容器类,作为主窗口
    class MainWindow(QWidget):
      def __init__(self):
        super().__init__()
        self.setWindowTitle("QWidget 基础容器示例")
        self.setStyleSheet("background-color: green;")  # 设置容器的显示样式,方便观察
        self.resize(300, 200)
    
        # 创建 QWidget 作为子容器
        son_container = QWidget(self)
        son_container.setGeometry(10, 10, 280, 180)  # 设置子容器的几何特征,位置为 (10, 10),大小为 (280, 180)
        son_container.setStyleSheet("background-color: red")  # 设置容器的显示样式,方便观察
        button = QPushButton("子容器的按钮", son_container)  # 创建按钮,作为子容器的子控件
        button.setStyleSheet("background-color: gray")  # 设置按钮的显示样式
        button.setGeometry(40, 50, 200, 40)  # 设置按钮的几何特征
    
    
    if __name__ == "__main__":
      app = QApplication(sys.argv)  # 创建 QApplication 对象
      main_window = MainWindow()  # 创建 MainWindow 实例对象
      main_window.show()   # 显示窗口
      sys.exit(app.exec())   # 退出应用程序

    放置了一个按钮在子容器中。


    • QFrame(带边框的容器)

            QFrame 继承自 QWidget,核心扩展是内置边框样式,适合需要视觉分隔的容器场景(如分组、分隔区域)。

    • 核心特性:
    1. 支持多种边框样式(如矩形、阴影、线条);
    2. 可设置边框宽度、颜色、阴影效果;
    3. 完全兼容 QWidget 的容器能力。

    常用边框样式(QFrame.Shape)

    样式常量说明
    QFrame.NoFrame无边框(默认)
    QFrame.Box矩形边框(带背景)
    QFrame.HLine/VLine水平 / 垂直线(分隔线)
    QFrame.Panel面板样式(凸起 / 凹陷)
    import sys
    from PySide6.QtWidgets import (QApplication, QWidget, QFrame, QPushButton)
    
    class MainWindow(QWidget):
      def __init__(self):
        super().__init__()
        self.setWindowTitle("QFrame 带边框容器示例")
        self.resize(350, 150)
    
        # 创建 QFrame 容器
        frame = QFrame(self)
        frame.setFrameShape(QFrame.Box) # 矩形边框
        frame.setFrameShadow(QFrame.Raised) # 凸起阴影
        frame.setLineWidth(2) # 边框宽度
        frame.setStyleSheet("background-color: green;")  # 背景色
        frame.setGeometry(60, 30, 230, 90)  # 设置容器位置和大小
    
        # 容器内的控件
        button = QPushButton("登录",frame)  # 添加按钮
        button.setGeometry(80, 30, 70, 30)  # 设置按钮位置和大小
        button.setStyleSheet("background-color: lightgray;")   # 按钮背景色
    
    
    
    if __name__ == "__main__":
      app = QApplication(sys.argv)
      window = MainWindow()
      window.show()
      sys.exit(app.exec())


    • QGroupBox(分组容器)

            QGroupBox 是专为逻辑分组设计的容器,自带可自定义的标题,支持折叠 / 展开(可选),适合将相关控件归类(如表单分组、功能模块分组)。

    • 核心特性:
    1. 显示分组标题(可设置对齐方式);
    2. 支持勾选框(setCheckable(True)),勾选时才启用组内控件;
    3. 视觉上有明显的分组边框。
    import sys
    from PySide6.QtWidgets import (QApplication, QWidget, QGroupBox,
                                   QVBoxLayout, QRadioButton, QCheckBox, QPushButton, QFrame)
    
    class MainWindow(QWidget):
      def __init__(self):
        super().__init__()
        self.setWindowTitle("QGroupBox 分组容器示例")
        self.resize(400, 400)
    
        # 创建一个QFrame对象作为分组容器的父控件
        frame = QFrame(self)
        frame.setGeometry(50, 50, 300, 300)
        frame.setStyleSheet("QFrame {border: 3px solid green;background-color: blue}")
    
        # 1. 创建分组容器
        group = QGroupBox("group群组容器", frame)  # group群组容器
        group.setGeometry(50, 50, 200, 100)   # 设置组容器位置和大小
        group.setStyleSheet("QGroupBox {border: 3px solid green;background-color: red};")  # 设置组容器背景色
    
        # 2. 群组内的按钮控件
        button_1= QPushButton("按钮1", group)
        button_2= QPushButton("按钮2", group)
        button_1.setGeometry(50, 20, 100, 30)
        button_2.setGeometry(50, 60, 100, 30)
    
        # 3. 另一个不属于群组的按钮
        button_3 = QPushButton("按钮3", frame)
        button_3.setGeometry(100, 200, 100, 30)
    
    
    if __name__ == "__main__":
      app = QApplication(sys.argv)
      window = MainWindow()
      window.show()
      sys.exit(app.exec())

    • QTabWidget(分页容器)

            QTabWidget 是多页面切换容器,通过标签页(Tab)分隔不同功能模块,适合界面功能较多、需要分页面展示的场景(如软件设置界面、多模块工具)。

    • 核心特性:
    1. 可添加多个标签页,每个标签页对应一个 QWidget 容器;
    2. 支持自定义标签文本、图标、关闭按钮;
    3. 可设置标签位置(上 / 下 / 左 / 右);
    4. 支持标签页切换信号(currentChanged)。
    • import sys
      
      from PySide6.QtWidgets import (QApplication, QWidget, QTabWidget,
                                     QLabel)
      
      
      class MainWindow(QWidget):
        def __init__(self):
          super().__init__()
          self.setWindowTitle("QTabWidget 分页容器示例")
          self.resize(400, 300)
      
          # 1. 创建分页容器
          tab_widget = QTabWidget(self)
          tab_widget.setTabPosition(QTabWidget.North) # 标签在顶部(默认)
          tab_widget.setTabsClosable(False) # 不显示关闭按钮
          tab_widget.setGeometry(10, 10, 380, 280)
      
          # 2. 页面1
          page1 = QWidget()
          label1 = QLabel("这是页面 1 的内容", page1)
          label1.setGeometry(50, 50, 100, 50)
          tab_widget.addTab(page1, "基础设置") # 添加页面,设置标签文本
      
          # 3. 页面2
          page2 = QWidget()
          label2 = QLabel("这是页面 2 ", page2)
          label2.setGeometry(50, 50, 100, 50)
          tab_widget.addTab(page2, "高级设置")  # 添加页面,设置标签文本
      
      
      
      if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec())

    
    
    • QScrollArea(滚动容器)

            当子控件内容超出可视区域时,QScrollArea 会自动显示滚动条,适合展示长列表、大表单、大图片等场景。

    • 核心特性
    1. 可以自动生成水平 / 垂直滚动条(按需显示);
    2. 可设置滚动条策略(始终显示 / 始终隐藏 / 按需);
    3. 子控件需通过 setWidget() 绑定。
    import sys
    from PySide6.QtWidgets import (QApplication, QWidget, QScrollArea, QPushButton)
    from PySide6.QtCore import Qt
    
    class MainWindow(QWidget):
      def __init__(self):
        super().__init__()
        self.setWindowTitle("QScrollArea 滚动容器示例")
        self.resize(300, 200)
    
        # 1. 创建滚动容器
        scroll_area = QScrollArea(self)
        # 设置滚动条策略
        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)  # 水平滚动条(按需显示)
        scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)    # 垂直滚动条(按需显示)
        scroll_area.setGeometry(0, 0, 150, 150)   # 滚动区域大小
    
        # 2. 创建子容器(承载大量控件)
        content_widget = QWidget(self)
        content_widget.setGeometry(0, 0, 300, 300)
    
        # 3. 添加大量按钮(超出可视区域)
        for i in range(20):
          btn = QPushButton(f"按钮 {i+1}", content_widget)
          btn.setGeometry(0, i * 40, 200, 30)
    
        # 4. 将子容器绑定到滚动区域
        scroll_area.setWidget(content_widget)
    
    
    
    if __name__ == "__main__":
      app = QApplication(sys.argv)
      window = MainWindow()
      window.show()
      sys.exit(app.exec())
    
    
    • QStackedWidget(堆叠容器)

            QStackedWidget 是不可见的分页容器(无标签页),同一时间只显示一个子控件(页面),适合通过按钮 / 下拉框手动切换页面的场景(如向导界面、步骤式操作)。

    • 核心特性
    1. 子控件以 “堆叠” 方式存放,仅显示当前索引的页面;
    2. 轻量级(无标签栏,节省界面空间);
    3. 支持通过 setCurrentIndex() 或 setCurrentWidget() 切换页面;
    4. 触发 currentChanged 信号。
    import sys
    from PySide6.QtWidgets import (QApplication, QWidget, QStackedWidget,
                   QVBoxLayout, QHBoxLayout, QPushButton, QLabel)
    
    class MainWindow(QWidget):
      def __init__(self):
        super().__init__()
        self.setWindowTitle("QStackedWidget 堆叠容器示例")
        self.resize(400, 400)
    
        # 1. 创建堆叠容器
        stacked_widget = QStackedWidget(self)
    
        # 2. 创建多个页面
        page1 = QLabel("堆叠页面 1  ", self)
        page1.setGeometry(50, 0, 300, 200)
    
        page2 = QLabel("堆叠页面 2  ", self)
        page2.setGeometry(50, 0, 300, 200)
    
        page3 = QLabel("堆叠页面 3  ", self)
        page3.setGeometry(50, 0, 300, 200)
    
    
        # 3. 添加页面到堆叠容器
        stacked_widget.addWidget(page1)
        stacked_widget.addWidget(page2)
        stacked_widget.addWidget(page3)
    
        # 4. 切换按钮
        btn_prev = QPushButton("上一步", self)
        btn_prev.setGeometry(100, 200, 100, 50)
        btn_next = QPushButton("下一步", self)
        btn_next.setGeometry(200, 200, 100, 50)
        btn_prev.clicked.connect(lambda: self.switch_page(stacked_widget, -1))   # 连接上一步按钮的点击事件
        btn_next.clicked.connect(lambda: self.switch_page(stacked_widget, 1))   # 连接下一步按钮的点击事件
    
    
    
      def switch_page(self, stacked, step):
        """切换页面"""
        current_idx = stacked.currentIndex()
        new_idx = current_idx + step
        # 边界检查
        if 0 <= new_idx < stacked.count():
          stacked.setCurrentIndex(new_idx)
    
    if __name__ == "__main__":
      app = QApplication(sys.argv)
      window = MainWindow()
      window.show()
      sys.exit(app.exec())

    三、容器控件选型指南

           

    容器控件核心场景关键优势
    QWidget通用容器、布局嵌套轻量、万能、无额外样式
    QFrame带边框的分隔区域内置边框样式、阴影效果
    QGroupBox逻辑分组、表单归类自带标题、支持勾选启用
    QTabWidget多标签页切换(可视化)直观的标签切换、易操作
    QScrollArea内容超出可视区域自动滚动、适配长内容
    QStackedWidget无标签页的页面切换轻量、节省空间、手动控制切换


    四、核心注意事项

    布局绑定:容器的子控件最好通过布局管理器(如 QVBoxLayout)绑定,否则子控件可能无法正  常显示 / 自适应;下一节将会学习布局管理器,并重新编写本节代码。

    父子关系:子控件的父对象需设置为容器,或通过布局添加(布局会自动设置父对象),否则控件可能 “丢失”;

    样式定制:可通过 setStyleSheet() 自定义容器的背景、边框、间距等样式;

    性能优化:对于大量子控件的容器(如 QScrollArea),建议使用 QListView/QTableView 等视图控件(而非手动添加大量按钮 / 标签),提升渲染性能。

            通过合理选择容器控件,可大幅提升 GUI 界面的结构化和易用性,结合布局管理器能实现灵活、自适应的界面布局。