PySide6 QMainWindow与QWidget秒解

我们用盖房子来理解 QMainWindow:

  • QWidget = 毛坯房:四面墙一个顶,什么都没有,所有东西都要自己装
  • QMainWindow = 开发商建好的精装修商品房:自带固定的功能分区(客厅、厨房、阳台),你只需要往里面摆家具就行

一句话核心 :QMainWindow 是 PySide6 专门用来做应用程序主窗口的类,它已经预设好了所有主窗口该有的标准结构,不用你从零搭建。

一、QMainWindow 的 "户型图":固定 5 大功能区

这是 QMainWindow 最关键的知识点 ------ 它有严格固定的布局结构,不能乱改,每个区域都有专属的 API:

⚠️ 最容易踩的坑 :QMainWindow不能直接用 setLayout () 加布局!它有自己内置的布局管理器,所有东西都必须放在上面 5 个区域里。

二、第一步:先 "收房"------ 创建一个空的主窗口

python 复制代码
import sys
from PySide6.QtWidgets import (QApplication, QMainWindow,
                               QLabel, QPushButton, QTextEdit)

# 继承QMainWindow,相当于"收房后开始个性化装修"
class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()  # 先调用父类的构造函数,拿到毛坯房
        self.init_ui()      # 开始装修
    
    def init_ui(self):
        # 设置窗口基本属性(相当于给房子挂门牌号、定大小)
        self.setWindowTitle("我的第一个主窗口")
        self.resize(800, 600)  # 宽800,高600
        # self.showMaximized() # 直接全屏显示

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()  # 开门迎客
    sys.exit(app.exec())

运行这个代码,你就得到了一个标准的空白主窗口。

三、第二步:装修 "客厅"------ 中心部件 Central Widget

中心部件是 QMainWindow 的灵魂,必须要有! 就像房子不能没有客厅。

  • 所有你想展示的核心内容(文本框、按钮、表格、图片)都要放在这里
  • 一个主窗口只能有一个中心部件
python 复制代码
def init_ui(self):
    self.setWindowTitle("我的第一个主窗口")
    self.resize(800, 600)
    
    # 1. 创建中心部件(相当于买个大沙发放在客厅)
    central_widget = QTextEdit()  # 用文本编辑器当中心部件
    # 2. 把中心部件设置给主窗口
    self.setCentralWidget(central_widget)
    
    # 如果你想放多个控件,就先创建一个QWidget,给它加布局,再设为中心部件
    # central_widget = QWidget()
    # layout = QVBoxLayout(central_widget)
    # layout.addWidget(QPushButton("按钮1"))
    # layout.addWidget(QLabel("标签1"))
    # self.setCentralWidget(central_widget)

菜单栏在窗口最顶部,是所有功能的总入口,就像家里玄关的总开关面板。

python 复制代码
def init_ui(self):
    # ... 前面的代码不变
    
    # 1. 获取主窗口自带的菜单栏(不用自己创建)
    menu_bar = self.menuBar()
    
    # 2. 添加一级菜单(相当于开关面板上的"灯光"、"空调"分组)
    file_menu = menu_bar.addMenu("文件")
    edit_menu = menu_bar.addMenu("编辑")
    help_menu = menu_bar.addMenu("帮助")
    
    # 3. 给菜单添加动作(相当于分组里的具体开关)
    new_action = file_menu.addAction("新建")
    open_action = file_menu.addAction("打开")
    file_menu.addSeparator()  # 添加分隔线
    save_action = file_menu.addAction("保存")
    file_menu.addSeparator()
    exit_action = file_menu.addAction("退出")
    
    # 4. 给动作绑定点击事件(按开关就触发对应的事)
    exit_action.triggered.connect(self.close)  # 点击退出就关闭窗口

五、第四步:放 "工具抽屉"------ 工具栏 Tool Bar

工具栏在菜单栏下面,放最常用的功能按钮,就像你放在茶几上的遥控器、手机,不用每次都去玄关开总开关。

python 复制代码
def init_ui(self):
    # ... 前面的代码不变
    
    # 1. 创建工具栏
    tool_bar = self.addToolBar("常用工具")
    
    # 2. 给工具栏添加动作(可以直接复用菜单栏的动作!)
    tool_bar.addAction(new_action)
    tool_bar.addAction(open_action)
    tool_bar.addAction(save_action)
    tool_bar.addSeparator()
    
    # 3. 也可以添加按钮、标签等其他控件
    tool_bar.addWidget(QPushButton("一键格式化"))
    
    # 4. 设置工具栏特性
    tool_bar.setMovable(True)  # 可以拖动(默认True)
    tool_bar.setFloatable(True) # 可以悬浮成独立窗口

六、第五步:挂 "留言板"------ 状态栏 Status Bar

状态栏在窗口最底部,用来显示临时提示信息或永久状态,就像门口的留言板。

python 复制代码
def init_ui(self):
    # ... 前面的代码不变
    
    # 1. 获取主窗口自带的状态栏
    status_bar = self.statusBar()
    
    # 2. 显示临时消息(5秒后自动消失)
    status_bar.showMessage("欢迎使用本程序", 5000)
    
    # 3. 显示永久消息(一直留在右下角)
    status_bar.addPermanentWidget(QLabel("版本:v1.0.0"))

七、完整可运行的例子

把上面所有部分拼起来,你就得到了一个有模有样的主窗口:

python 复制代码
import sys
from PySide6.QtWidgets import (QApplication, QMainWindow,
                               QLabel, QPushButton, QTextEdit)

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
    
    def init_ui(self):
        self.setWindowTitle("迷你记事本")
        self.resize(800, 600)
        
        # 1. 中心部件
        self.text_edit = QTextEdit()
        self.setCentralWidget(self.text_edit)
        
        # 2. 菜单栏
        menu_bar = self.menuBar()
        file_menu = menu_bar.addMenu("文件")
        
        new_action = file_menu.addAction("新建")
        open_action = file_menu.addAction("打开")
        save_action = file_menu.addAction("保存")
        file_menu.addSeparator()
        exit_action = file_menu.addAction("退出")
        exit_action.triggered.connect(self.close)
        
        # 3. 工具栏
        tool_bar = self.addToolBar("工具栏")
        tool_bar.addAction(new_action)
        tool_bar.addAction(open_action)
        tool_bar.addAction(save_action)
        
        # 4. 状态栏
        self.statusBar().showMessage("就绪", 3000)
        self.statusBar().addPermanentWidget(QLabel("迷你记事本 v1.0"))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    sys.exit(app.exec())

八、一句话总结核心

部件 类比 作用
QMainWindow 精装修商品房 主窗口容器,自带固定结构
中心部件 客厅 放核心内容,必须有且只有一个
菜单栏 玄关总开关 所有功能的总入口
工具栏 茶几遥控器 放最常用的功能,快速访问
状态栏 门口留言板 显示程序状态和提示信息

新手黄金法则:做主窗口就用 QMainWindow,不要用 QWidget;所有控件都放在 5 个固定区域里,永远不要给 QMainWindow 直接 setLayout ()。

PySide6 QWidget:用 "毛坯房" 秒懂所有控件的祖宗

延续之前的 "盖房子" 系列,我们用毛坯房来理解 QWidget,这样你就能一眼看清它和 QMainWindow 的本质区别:

  • QWidget = 纯毛坯房:只有四面墙、一个顶、一个门,什么都没有。水电要自己拉,地板要自己铺,家具要自己买,想怎么装就怎么装
  • QMainWindow = 精装修商品房:开发商已经帮你做好了固定的功能分区(客厅、厨房、阳台),你只需要往里面摆家具就行

一句话核心 :QWidget 是 PySide6 中所有 UI 控件的基类(按钮、标签、文本框、窗口... 全都是 QWidget 的子类)。它是最基础、最灵活、最空白的组件,没有任何预设结构,完全由你自由定制。

一、QWidget 的核心本质

你可以把 QWidget 理解成一个万能的 "容器",它有三重身份:

  1. 独立窗口:就是我们平时看到的各种弹窗、对话框
  2. 子容器:用来分组管理其他控件(比如一个面板、一个功能区)
  3. 基础控件:所有具体控件(QLabel、QPushButton、QTextEdit)本质上都是特殊的 QWidget

⚠️ 最容易踩的坑 :QWidget必须自己设置布局 !否则所有控件都会堆在左上角,窗口缩放时也不会自动调整大小。这和 QMainWindow 正好相反(QMainWindow 不能直接调用setLayout())。

二、第一步:先 "盖好" 一个毛坯房

python 复制代码
import sys
from PySide6.QtWidgets import QApplication, QWidget

# 继承QWidget,相当于"拿到一块地,开始盖毛坯房"
class MyWindow(QWidget):
    def __init__(self):
        super().__init__()  # 先调用父类的构造函数,打好地基
        self.init_ui()      # 开始装修
    
    def init_ui(self):
        # 设置窗口基本属性(相当于给房子挂门牌号、定大小)
        self.setWindowTitle("我的第一个毛坯房窗口")
        self.resize(600, 400)  # 宽600,高400
        # self.setFixedSize(600, 400) # 固定窗口大小,禁止缩放

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyWindow()
    window.show()  # 开门迎客
    sys.exit(app.exec())

运行这个代码,你就得到了一个最纯粹的空白窗口,什么都没有,干干净净。

三、第二步:最重要的一步 ------"装水电铺地板"(设置布局)

这是 QWidget 最核心、最容易出错的地方。毛坯房不能直接摆家具,必须先铺好地板、走好水电,也就是设置布局管理器

布局管理器就像你给房子画的 "装修平面图",它会自动帮你排列控件,窗口缩放时也会智能调整大小和位置。

PySide6 有 4 种常用布局,对应 4 种不同的排列方式:

布局类型 装修类比 核心作用
QHBoxLayout 横向摆放家具 控件水平排成一排
QVBoxLayout 纵向摆放家具 控件垂直排成一列
QGridLayout 地砖格子 控件排成网格状(几行几列)
QFormLayout 填表格式 专门用来做 "标签 + 输入框" 的表单

我们用最常用的垂直布局来举例:

python 复制代码
from PySide6.QtWidgets import QVBoxLayout

def init_ui(self):
    self.setWindowTitle("我的第一个毛坯房窗口")
    self.resize(600, 400)
    
    # 1. 创建布局管理器(相当于画好装修平面图)
    # 把布局直接绑定到当前窗口(self)
    main_layout = QVBoxLayout(self)
    
    # 2. 设置布局的边距和间距(相当于留好墙距和家具间距)
    main_layout.setContentsMargins(30, 30, 30, 30)  # 左、上、右、下边距
    main_layout.setSpacing(20)  # 控件之间的间距

四、第三步:往里面 "摆家具"(添加控件)

布局设置好之后,就可以往里面添加各种控件了,就像往摆好平面图的房子里放沙发、电视、桌子一样。

python 复制代码
from PySide6.QtWidgets import QLabel, QLineEdit, QPushButton

def init_ui(self):
    # ... 前面的代码不变
    
    # 1. 添加标签(相当于在墙上挂一幅画)
    # 注意:加self.变成实例属性,这样其他方法也能访问到
    self.title_label = QLabel("欢迎来到我的毛坯房")
    # 设置标签样式(相当于给画装个好看的框)
    self.title_label.setStyleSheet("font-size: 24px; font-weight: bold; color: #2563eb;")
    # 把标签添加到布局里
    main_layout.addWidget(self.title_label)
    
    # 2. 添加输入框(相当于装一个洗手池)
    self.name_input = QLineEdit()
    self.name_input.setPlaceholderText("请输入你的名字")
    main_layout.addWidget(self.name_input)
    
    # 3. 添加按钮(相当于装一个电灯开关)
    hello_button = QPushButton("打个招呼")
    main_layout.addWidget(hello_button)
    
    # 4. 添加弹性空间(相当于留一块空地)
    # 这样上面的控件会靠上对齐,下面自动留空
    main_layout.addStretch()

五、第四步:"安装开关"(连接信号与槽)

家具摆好了,开关也装好了,现在需要把开关和电器连接起来,这样按开关的时候电器才会工作。这就是 PySide6 的灵魂 ------信号与槽机制

  • 信号:控件发出的 "通知"(比如按钮被点击了、输入框内容改变了)
  • 槽:接收到信号后要执行的 "动作"(比如弹出提示框、显示一段文字)
python 复制代码
def init_ui(self):
    # ... 前面的代码不变
    
    # 把按钮的"点击"信号,连接到我们自己写的"say_hello"槽函数
    hello_button.clicked.connect(self.say_hello)

# 定义槽函数(相当于开关按下后要做的事)
def say_hello(self):
    # 获取输入框里的名字
    name = self.name_input.text().strip()
    if name:
        self.title_label.setText(f"你好,{name}!欢迎来到我的毛坯房")
    else:
        self.title_label.setText("你好,陌生人!请先输入你的名字")

六、完整可运行的例子

把上面所有部分拼起来,你就得到了一个简单但完整的 QWidget 窗口:

python 复制代码
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout,
                               QLabel, QLineEdit, QPushButton)

class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()
    
    def init_ui(self):
        self.setWindowTitle("我的第一个毛坯房窗口")
        self.resize(600, 400)
        
        # 创建垂直布局
        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(30, 30, 30, 30)
        main_layout.setSpacing(20)
        
        # 添加标签
        self.title_label = QLabel("欢迎来到我的毛坯房")
        self.title_label.setStyleSheet("font-size: 24px; font-weight: bold; color: #2563eb;")
        main_layout.addWidget(self.title_label)
        
        # 添加输入框
        self.name_input = QLineEdit()
        self.name_input.setPlaceholderText("请输入你的名字")
        main_layout.addWidget(self.name_input)
        
        # 添加按钮
        hello_button = QPushButton("打个招呼")
        hello_button.clicked.connect(self.say_hello)
        main_layout.addWidget(hello_button)
        
        # 添加弹性空间
        main_layout.addStretch()
    
    def say_hello(self):
        name = self.name_input.text().strip()
        if name:
            self.title_label.setText(f"你好,{name}!欢迎来到我的毛坯房")
        else:
            self.title_label.setText("你好,陌生人!请先输入你的名字")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec())

七、QWidget 的独门绝技:嵌套布局

毛坯房的最大优势就是无限灵活,你可以在一个布局里嵌套另一个布局,就像你可以把房子分成客厅、卧室、厨房一样。

比如,我们想在窗口底部放两个并排的按钮,就可以用一个水平布局嵌套在垂直布局里:

python 复制代码
from PySide6.QtWidgets import QHBoxLayout

def init_ui(self):
    # ... 前面的代码不变
    
    # 创建一个水平布局,专门用来放底部的两个按钮
    button_layout = QHBoxLayout()
    
    # 添加两个按钮到水平布局
    button_layout.addWidget(QPushButton("确定"))
    button_layout.addWidget(QPushButton("取消"))
    
    # 把水平布局添加到主垂直布局的最底部
    main_layout.addLayout(button_layout)

八、QWidget vs QMainWindow:一张表搞懂什么时候用哪个

特性 QWidget(毛坯房) QMainWindow(精装修商品房)
预设结构 完全空白,什么都没有 自带菜单栏、工具栏、状态栏、中心部件、停靠区
布局方式 必须自己调用 setLayout () 不能直接调用 setLayout (),有内置布局
灵活性 最高,想怎么装就怎么装 中等,必须使用固定的 5 个区域
适用场景 弹窗、对话框、子窗口、自定义控件 应用程序的主窗口
学习成本 低,简单直接 高,有很多专属 API

九、新手黄金法则

  1. 主窗口用 QMainWindow,其他所有窗口 / 面板 / 控件都用 QWidget
  2. 永远先设置布局,再添加控件,绝对不要手动设置控件的 x、y 坐标
  3. 需要复杂排列时就用嵌套布局,不要试图用一个布局搞定所有事情
  4. 所有需要在多个方法中访问的控件,都要加 self. 变成实例属性
相关推荐
Scott9999HH5 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社6 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海6 小时前
python 列表、元组、集合和字典
开发语言·python
二十雨辰6 小时前
[爬虫]-Urllib
爬虫·python
萧瑟余晖7 小时前
JDK 26 新特性详解
java·开发语言
马优晨7 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
玉鸯8 小时前
Agent Hook:在概率推理之上,为 Agent 叠加确定性控制
python·langchain·agent
weixin_446260859 小时前
HACO:面向动态部署环境的对冲式智能计算可靠多智能体调度框架
后端·python·flask
我的xiaodoujiao9 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest