Day 3

高级控件 Model/View / 事件机制 / 文件 IO 与 JSON

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

  • 模块 A(3 课时):Model/View 架构 / 事件机制
  • 模块 B(3 课时):文件 IO / JSON 解析 → 本地数据存储案例

模块 A · 讲授 35min

Model/View 架构 / 事件机制

Model/View 模型视图架构(教学补充)


// 模型:只管数据
auto* model = new QStandardItemModel(this);
model->appendRow(new QStandardItem(QStringLiteral("需求分析")));

// 视图:只管展示,不持有数据
auto* view = new QListView(this);
view->setModel(model);

// 选中状态变化 → 通知外部,模型和视图之间没有直接耦合
connect(view->selectionModel(), &QItemSelectionModel::currentChanged, ...);
    

出处:docs/teaching/examples/model_view/qt_model_view_basics.cpp配套 README)—— 仓库 p03/ 的 wiki 抓取内容没有 Model/View,这是本轮补写的教学补充示例,已离屏验证跑通。

事件循环机制(复用 Day2 概念)

app.exec() 进入的就是事件循环——鼠标点击、键盘输入、定时器 触发都会变成事件,被塞进这个循环里依次分发。今天讲的"事件过滤器"就是在 事件被分发给控件之前,插一个"拦截点"。

出处:p03/ch02/minimal_qt_app.cpp

自定义事件处理 / 事件过滤器


class EventLabel : public QLabel {
    Q_OBJECT
public:
    explicit EventLabel(QWidget* p=nullptr):QLabel(p){ setMouseTracking(true); }
protected:
    void mouseMoveEvent(QMouseEvent* event) override {
        setText(QString("Move: (%1, %2)").arg(event->x()).arg(event->y()));
    }
};
    

重写 xxxEvent 是 Qt 事件处理的主线之一(另一条线是事件过滤器 installEventFilter)。出处:p03/ch09/mouse_event.cpp; 事件过滤器见 event_filter_mainwindow.cpp

模块 A · 练习 95min

动手:Model/View + 事件

任务卡 1 · Model/View 换视图

目标
qt_model_view_basics.cpp 里的 QListView 换成 QTableView,模型代码不改
验收标准
编译通过,界面正常展示同一份数据,证明"同一个模型可以喂给不同视图"
基础知识 · 参考
qt_model_view_basics.cpp · README

任务卡 2 · 事件过滤器实操

目标
仿 event_filter_mainwindow.cpp,给一个控件装事件过滤器,拦截鼠标按下事件并打印坐标
验收标准
点击控件后终端/调试输出能看到坐标信息
基础知识 · 参考
event_filter_mainwindow.cpp · mouse_event.cpp

模块 B · 讲授 35min

文件 IO / JSON 解析

文件系统:QFile 读文本


QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "打开失败"; return -1; }
while (!file.atEnd()) { qDebug() << file.readLine(); }
    

出处:p03/ch11/qfile_basic.cpp;结构化读写见 qtextstream_io.cppqdatastream_io.cpp

JSON 解析与写入(教学补充)


QJsonObject student;
student["name"] = QStringLiteral("张三");
student["score"] = 92;

QJsonDocument doc(student);
QByteArray bytes = doc.toJson(QJsonDocument::Indented);   // 序列化

QJsonDocument parsed = QJsonDocument::fromJson(bytes);     // 反序列化
QJsonObject obj = parsed.object();
qDebug() << obj["name"].toString() << obj["score"].toInt();
    

出处:docs/teaching/examples/json_io/qt_json_parse_write.cpp配套 README)—— 仓库 p03/ch11 的 wiki 抓取内容只有 QFile/QTextStream/QDataStream,没有 JSON, 这是本轮补写的教学补充示例;不需要 GUI,tools/run_qt.sh qt_json_parse_write 直接跑即可,不需要 QT_QPA_PLATFORM=offscreen

模块 B · 练习 95min(本地数据存储案例,练习任务,非预建方案)

动手:本地数据存储小工具

任务卡 1 · JSON 落盘

目标
qt_json_parse_write.cpp 的 JSON 数据实际写入一个文件(结合 qfile_basic.cppQFile 写法),再读回来解析校验
验收标准
程序运行后磁盘上生成一个 .json 文件,内容可读;重新运行程序能正确解析出 之前写入的数据
基础知识 · 参考
qt_json_parse_write.cpp · README · qfile_basic.cpp

任务卡 2 · 本地数据存储小工具

目标
设计一个"学员信息"结构(姓名/成绩/标签),支持增加一条记录并追加保存到 JSON 文件, 重启程序后能读出之前保存的全部记录
验收标准
至少能存 2 条以上记录并在重启后完整读回;数据字段不丢失
基础知识 · 参考
docs/teaching/examples/json_io/ · qtextstream_io.cpp

当日产出验证

现场演示

现场演示本地数据存储小工具,验证"写入 → 重启 → 读回"完整闭环。

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