# Day 2

### Qt 开发环境 / 信号槽 / 基础控件 / 布局与 QSS

C++/Qt 方向实训 · 第 2 / 5 天 · 讲:练 ≈ 1:2.7

- 模块 A（3 课时）：项目结构 / 第一个程序 / 信号槽
- 模块 B（3 课时）：常用控件 / 布局管理 / QSS 界面美化 → 计算器案例

#### 开始前准备（一次性）

    tools/install_qt_host.sh
    cmake -S . -B build -G Ninja -DBUILD_QT_PART=ON \
          -DCMAKE_PREFIX_PATH=$PWD/.qt514/5.14.2/gcc_64 -DCMAKE_BUILD_TYPE=Debug
    cmake --build build

模块 A · 讲授 35min

## 项目结构 / 信号槽 讲

- 最小 Qt 程序结构
- 控件创建与显示
- 内置 / 自定义 / lambda 信号槽

### 最小 Qt 程序：QApplication + exec() 讲

    class Widget : public QWidget {
        Q_OBJECT   // 用到信号槽/属性系统的类都要有这个宏（触发 moc 代码生成）
    public:
        Widget(QWidget* parent = nullptr) : QWidget(parent) {}
    };

    int main(int argc, char* argv[]) {
        QApplication app(argc, argv);   // 整个程序唯一的 QApplication
        Widget w;
        w.show();
        return app.exec();              // 进入事件循环，程序在这里“活着”
    }

出处：p03/ch02/minimal_qt_app.cpp（注意仓库版本额外注入了 `QTimer::singleShot` 200ms 自动退出，便于离屏自动化验证，真实项目不需要这一行）

### 控件创建：两种写法 讲

    // 第一种：先构造再设属性
    QPushButton* btn = new QPushButton;
    btn->setParent(this);
    btn->setText(QStringLiteral("德玛西亚"));
    btn->move(100, 100);

    // 第二种：构造时指定文本与父亲
    QPushButton* btn2 = new QPushButton(QStringLiteral("孙悟空"), this);

出处：p03/ch03/button_creation.cpp

### 信号槽：内置 / 自定义 / 重载消歧义 讲

    class Teacher : public QObject {
        Q_OBJECT
    signals:
        void hungry();             // 无参信号
        void hungry(QString food); // 带参信号（重载）
    public slots:
        void classIsOver(){ emit hungry(); emit hungry(QString("汉堡")); }
    };
    // 连接重载信号时必须用 QOverload 显式指定版本
    connect(t, QOverload<>::of(&Teacher::hungry), s, QOverload<>::of(&Student::treat));
    connect(t, QOverload<QString>::of(&Teacher::hungry), s, QOverload<QString>::of(&Student::treat));

出处：p03/ch04/custom_signal_slot.cpp； lambda 槽 + 值捕获/引用捕获对比见 lambda_signal_slot.cpp

模块 A · 练习 95min

## 动手：第一个 Qt 程序 练

#### 任务卡 1 · 跑通最小程序 练

目标
  编译运行 `minimal_qt_app` 与 `button_creation`
验收标准
  `QT_QPA_PLATFORM=offscreen tools/run_qt.sh minimal_qt_app` 与 `button_creation` 均退出码为 0，无崩溃
基础知识 · 参考
  p03/ch02/minimal_qt_app.cpp · p03/ch03/button_creation.cpp

#### 任务卡 2 · 自定义信号槽改文本 练

目标
  给一个按钮连接自定义信号槽：点击后改变一个 `QLabel` 的文本内容
验收标准
  编译通过；离屏或有 X 环境下点击/模拟点击后 `QLabel` 文本确实改变； 用 `connect` 语法而非直接函数调用
基础知识 · 参考
  custom_signal_slot.cpp（主参考）· lambda_signal_slot.cpp（lambda 槽写法对比）

#### 任务卡 3（选做）· 重载信号消歧义 练

目标
  仿 `builtin_signal_slot.cpp`，给一个类定义两个同名不同参的信号，用 `QOverload` 消歧义连接
验收标准
  两个重载信号都能各自触发对应的槽
基础知识 · 参考
  p03/ch04/builtin_signal_slot.cpp

模块 B · 讲授 35min

## 常用控件 / 布局管理 / QSS 美化 讲

### 常用控件：QLabel 显示图片 讲

    QPixmap pixmap;
    pixmap.load(":/Image/boat.jpg");   // 从 Qt 资源系统（.qrc）加载
    QLabel* label = new QLabel(this);
    label->setPixmap(pixmap);

出处：p03/ch08/label_pixmap.cpp； HTML 富文本标签见 label_text_html.cpp

### 自定义控件与布局：QHBoxLayout 讲

    QSpinBox* spin = new QSpinBox(this);
    QSlider* slider = new QSlider(Qt::Horizontal, this);
    QHBoxLayout* layout = new QHBoxLayout(this);
    layout->addWidget(spin);
    layout->addWidget(slider);
    // spin 变化 → slider 跟随，slider 变化 → spin 跟随
    connect(spin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), slider, &QSlider::setValue);
    connect(slider, &QSlider::valueChanged, spin, &QSpinBox::setValue);

出处：p03/ch08/custom_widget.cpp——布局管理器负责排布， 不用手算控件坐标。

### QSS 界面美化（教学补充） 讲

    okBtn->setObjectName("okButton");
    setStyleSheet(
        "QPushButton#okButton { background-color: #2f855a; border-radius: 6px; color: white; }"
        "QPushButton#okButton:hover { background-color: #276749; }"
    );

出处：docs/teaching/examples/qss_styling/qt_qss_styling.cpp （配套 README）—— 仓库 `p03/` 的 wiki 抓取内容没有 QSS，这是本轮补写的教学补充示例，已离屏验证跑通。

模块 B · 练习 95min（计算器案例，练习任务，非预建方案）

## 动手：做一个计算器 练

#### 任务卡 1 · 计算器雏形 练

目标
  组合 `button_creation.cpp`（数字/运算符按钮）+ `custom_signal_slot.cpp` （点击信号槽）+ `custom_widget.cpp`（布局排布按钮），做出一个能加减乘除的最小计算器
验收标准
  至少支持两个数 + 一种运算符的计算并在 `QLabel`/`QLineEdit` 上正确显示结果； 界面不重叠、按钮可点击
基础知识 · 参考
  button_creation.cpp · custom_signal_slot.cpp · custom_widget.cpp

#### 任务卡 2 · 用 QSS 美化计算器 练

目标
  给任务卡 1 的计算器套一份 QSS 样式（数字键/运算键/等号键区分颜色）
验收标准
  至少 2 类按钮有不同的 `background-color`；至少 1 个按钮有 `:hover` 或 `:pressed` 效果
基础知识 · 参考
  qt_qss_styling.cpp · README

## 当日产出验证

#### 现场演示

    QT_QPA_PLATFORM=offscreen tools/run_qt.sh <target>
    # 有 X 环境：去掉 QT_QPA_PLATFORM=offscreen 直接看窗口

现场演示计算器，至少完成一次正确运算 + QSS 美化。

返回目录 · ← 上一天 · 下一天 →