Qt贪吃蛇

ui->setupUi(this);那这里的this指针指的不是当前界面的这个GameWindow对象吗,ui(new Ui::GameWindow)是在做什么

cpp 复制代码
GameWindow::GameWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::GameWindow)//创建一个Ui::GameWindow对象,这个对象不是窗口本身,而是一个助手对象,负责创建和管理窗口中的所有控件
{
    ui->setupUi(this);
    // 设置窗口大小
    setFixedSize(WIDTH, HEIGHT);

    // 设置窗口标题
    setWindowTitle("贪吃蛇游戏");

    // 初始化游戏
    initGame();
}

问得好!这两个概念容易混淆。让我详细解释:

ui(new Ui::GameWindow) vs ui->setupUi(this)

1. ui(new Ui::GameWindow) - 创建UI对象

cpp

复制代码
Ui::GameWindow *ui;  // 声明UI指针

// 在构造函数初始化列表中:
ui(new Ui::GameWindow)

这是什么?

  • 创建一个 Ui::GameWindow 对象

  • 这个对象不是 窗口本身,而是一个助手对象

  • 它负责创建和管理窗口中的所有控件

内存关系

text

复制代码
堆内存:
┌─────────────────────────────────────────┐
│ Ui::GameWindow 对象 (ui指针指向这里)     │
│ 包含:                                    │
│ - QPushButton *pushButtonStart;         │
│ - QLabel *labelScore;                   │
│ - 其他控件的指针...                      │
└─────────────────────────────────────────┘

2. this - 当前GameWindow对象

cpp

复制代码
ui->setupUi(this);

this 是什么?

  • 指向当前 GameWindow 实例的指针

  • 就是显示在屏幕上的那个窗口

内存关系

text

复制代码
栈内存/堆内存:
┌─────────────────────────────────────────┐
│ GameWindow 对象 (this指向这里)           │
│ 包含:                                    │
│ - QMainWindow 的基础部分                 │
│ - Ui::GameWindow *ui (成员变量)         │
│ - 其他成员变量...                        │
└─────────────────────────────────────────┘

实际创建过程分解

步骤1:创建UI对象

cpp

复制代码
ui = new Ui::GameWindow;
  • 在堆上分配一个 Ui::GameWindow 对象

  • 此时对象是的,还没有创建任何控件

  • ui 只是一个"工厂",能生产控件

步骤2:创建所有控件

cpp

复制代码
ui->setupUi(this);

这里发生了很多事情,相当于:

cpp 复制代码
void Ui::GameWindow::setupUi(QMainWindow *window)
{
    // 1. 创建中央部件
    QWidget *centralWidget = new QWidget(window);
    window->setCentralWidget(centralWidget);
    
    // 2. 创建布局
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);
    
    // 3. 创建所有子控件
    labelScore = new QLabel("得分: 0", centralWidget);
    pushButtonStart = new QPushButton("开始", centralWidget);
    
    // 4. 添加到布局
    layout->addWidget(labelScore);
    layout->addWidget(pushButtonStart);
    
    // 5. 设置窗口标题等
    window->setWindowTitle("贪吃蛇游戏");
}

完整的内存关系图

text

复制代码
内存示意图:

┌─────────────────────────────────────────────────────┐
│        GameWindow 对象 (this)                       │
│        (显示在屏幕上的窗口)                        │
├─────────────────────────────────────────────────────┤
│ 成员变量:                                          │
│  ┌─────────────────────────────────────────────┐   │
│  │ ui: 0x12345678 (指向UI对象)                 │   │
│  └─────────────────────────────────────────────┘   │
│ 其他成员变量...                                     │
│                                                    │
│ 包含的Qt控件(实际由ui对象创建):                  │
│  ┌─────────────┐  ┌─────────────────┐            │
│  │ QLabel      │  │ QPushButton     │            │
│  │ "得分: 0"   │  │ "开始游戏"      │            │
│  └─────────────┘  └─────────────────┘            │
│                                                    │
│ 注意:这些控件是GameWindow的子对象,但不是成员变量│
└─────────────────────────────────────────────────────┘
         ↑
         │ ui指针指向
         ↓
┌─────────────────────────────────────────────────────┐
│        Ui::GameWindow 对象 (ui)                     │
│        (看不见的助手对象)                          │
├─────────────────────────────────────────────────────┤
│ 成员变量(都是指针):                              │
│   QLabel *labelScore;       → 指向上面的QLabel     │
│   QPushButton *pushButtonStart; → 指向上面的按钮    │
│                                                    │
│ 重要:这些指针只是"引用",不拥有控件!              │
│ 控件真正的父对象是 GameWindow (this)               │
└─────────────────────────────────────────────────────┘

关键区别总结

对比项 ui (Ui::GameWindow对象) this (GameWindow对象)
是什么 助手对象,创建和管理控件 实际的窗口对象
可见性 不可见,在后台工作 可见,显示在屏幕上
作用 创建控件并保存它们的指针 作为控件的父容器
内存 包含控件的指针 包含控件的实际对象
生命周期 由GameWindow管理 窗口本身

为什么需要两个对象?

设计原理:关注点分离

  1. Ui::GameWindow 只负责:

    • 创建界面控件

    • 设置界面布局

    • 保存控件指针以便访问

  2. GameWindow 负责:

    • 显示窗口

    • 处理业务逻辑

    • 响应用户交互

Qt的对象树机制

Qt有一个重要的特性:对象树父子关系

cpp

复制代码
ui->setupUi(this);

这行代码的关键作用是:

  1. 创建的所有控件都以 this 为父对象

  2. this (GameWindow) 被删除时,自动删除所有子控件

  3. 控件之间的信号槽连接会自动管理

cpp 复制代码
// Qt自动管理的内存释放:
GameWindow::~GameWindow()
{
    delete ui;  // 只删除ui对象本身
    
    // 注意:不删除控件!
    // 控件会在GameWindow删除时自动删除
    // 因为它们是GameWindow的子对象
}

总结比喻

把整个系统想象成一个工厂

  • this (GameWindow) = 工厂大楼

    • 看得见的建筑

    • 包含所有机器和工人

    • 对外营业

  • ui (Ui::GameWindow对象) = 工厂的安装团队

    • 看不见的后台团队

    • 负责安装和设置所有机器

    • 保存机器的位置图(指针)

    • 完工后就没事了

  • ui->setupUi(this) = 安装团队进入工厂安装设备

    • 在工厂大楼里安装所有机器

    • 把机器位置记录在图纸上

    • 完成后,工厂可以开始运营

所以,ui 只是创建和记录 控件,而 this 才是容纳和显示控件的真正窗口。

相关推荐
rabbit_pro1 小时前
Java 执行FFmpeg命令
java·开发语言·ffmpeg
C.L.L1 小时前
C++ vscode调试——如何方便查看动态二维矩阵
开发语言·c++·矩阵
.小小陈.1 小时前
C++初阶4:STL简介
开发语言·c++·学习
白日做梦Q1 小时前
ICMP互联网控制报文协议的详细介绍(基本概念、用处、故障排查)
开发语言·网络·php
毒鸡蛋1 小时前
绘制火山图 R、python
开发语言·python·r语言
听风吟丶1 小时前
Java 响应式编程实战:Spring WebFlux+Reactor 构建高并发电商系统
java·开发语言·spring
Aerelin1 小时前
爬虫图片采集(自动化)
开发语言·前端·javascript·爬虫·python·html
枫叶丹41 小时前
浙人医信创实践:电科金仓异构多活架构破解集团化医院转型难题
开发语言·数据库·架构