# Model/View 模型视图架构 —— 教学补充示例

> 对应方案书「C++方向 Day3」："高级控件应用与 Model/View 模型视图架构"。
> 仓库 `p03/` 的 wiki 抓取内容里没有 Model/View 相关代码，本示例是手工补写的
> 教学补充，**不属于** `tools/gen_part3.py` 的生成产物。

## 概念

Qt 的 Model/View 架构把"数据"和"展示"彻底解耦成三层：

- **Model**（模型）：只管数据，不知道自己会被怎么展示。本示例用现成的
  `QStandardItemModel`（也可以继承 `QAbstractListModel`/`QAbstractTableModel`
  自己实现，工作量更大，教学上先用现成模型建立概念）；
- **View**（视图）：只管展示和交互，不持有数据副本，展示什么完全来自
  `setModel()` 绑的那个模型。本示例用 `QListView`；
- **Selection Model**（选中状态）：视图的选中状态也被抽成独立对象
  `QItemSelectionModel`，可以多个视图共享同一个选中状态。

对比"没有 Model/View"的写法（比如直接往 `QListWidget` 里塞 `addItem()`）：数据
和展示是绑死的；Model/View 的好处在于同一份数据可以同时喂给
`QListView`/`QTableView`/`QComboBox` 等多个视图，改数据所有视图自动同步。

## 代码走读

见 [`qt_model_view_basics.cpp`](qt_model_view_basics.cpp)：

1. 建一个 `QStandardItemModel`，塞 4 行字符串数据；
2. 建一个 `QListView`，`setModel()` 绑定上面的模型——视图本身不存数据；
3. 监听 `view->selectionModel()->currentChanged` 信号，选中项变化时更新一个
   `QLabel`，体现"视图状态变化 → 通知外部"的解耦方式；
4. 代码末尾手动 `setCurrentIndex()` 选中第一行，是为了离屏自动化验证时也能
   触发一次 `currentChanged`（真实交互中这一步由用户点击触发）。

## 验证方式

```bash
QT_QPA_PLATFORM=offscreen tools/run_qt.sh qt_model_view_basics
```

## 练习方向（供任务卡引用）

- 把 `QListView` 换成 `QTableView`，模型不变，观察"同一份模型换个视图"是怎么
  做到的；
- 增加一个"删除选中行"按钮，调用 `model->removeRow(view->currentIndex().row())`，
  体会数据变化后视图自动刷新（不需要手动重画）。

## 参考

- Qt 官方文档：*Model/View Programming*（doc.qt.io，选读·需联网）
