PlainTextEdit 组件实现 教学总结
Table of Contents
- 一、这个模块到底在学什么
- 1. 输入层
- 2. 文本结构层
- 3. 数据容器层
- 4. 视图层
- 二、每个模块 / 函数的详细教学
- A. QPlainTextEdit 详细教学
- A.1 它是什么
- QPlainTextEdit
- QTextEdit
- A.2 这次为什么不用 QLineEdit
- A.3 最核心接口
- B. QTextDocument 详细教学
- B.1 它是什么
- B.2 这次为什么要先拿 document()
- B.3 最核心接口:blockCount()
- C. QTextBlock 详细教学
- C.1 它是什么
- C.2 最核心接口:findBlockByNumber()
- C.3 text()
- C.4 为什么这比手写字符串分割更有教学价值
- D. QStringList 详细教学
- D.1 它是什么
- D.2 这次为什么它合适
- D.3 最常见操作
- E. QStringListModel 详细教学
- E.1 它是什么
- E.2 这次为什么必须用它
- E.3 最核心构造方式
- E.4 为什么我让你加 this
- F. QListView 详细教学
- F.1 它是什么
- QListWidget
- QListView
- F.2 这次为什么用 QListView
- F.3 最核心接口:setModel()
- 三、状态栏相关内容的详细教学
- A. QStatusBar 是什么
- B. 这次你怎么用的
- C. 为什么这次状态栏不是核心,但仍值得认识
- 四、为什么这里用 Model/View,而不是直接往界面塞文本
- 五、本模块新增模块的重点系统总结
- 1. QPlainTextEdit
- 定义
- 适合场景
- 本次作用
- 2. QTextDocument
- 定义
- 核心接口
- 本次作用
- 3. QTextBlock
- 定义
- 核心接口
- 本次作用
- 4. QStringList
- 定义
- 本次作用
- 5. QStringListModel
- 定义
- 本次作用
- 6. QListView
- 定义
- 核心接口
- 本次作用
- 7. QStatusBar
- 定义
- 本次作用
- 六、这个模块最重要的知识点
- 1. QPlainTextEdit 适合多行纯文本,不是富文本
- 2. 文本控件背后有文档模型
- 3. QListView 本身不存数据,它依赖模型
- 4. 逐行处理文本时,QTextDocument + QTextBlock 是一种标准思路
- 七、这个模块最容易踩的坑
- 易错点 1:把 QListView 当成 QListWidget
- 易错点 2:忘记给 QStringListModel 设父对象
- 易错点 3:误以为 blockCount() 就一定等于“非空行数”
- 易错点 4:主窗口不是 QMainWindow
- 八、你现在应该形成的理解
- 九、这一模块最值得记住的最小模板
Protected content
请输入课程内容访问密码
很好。现在进入 PlainTextEdit:阶段 2(教学总结)。
先给结论:
这一项真正要掌握的,不只是“多行文本能读出来”,而是 Qt 中文本对象模型 + Model/View 显示链。这次代码实际上完成了这样一条路径:
这已经不是单个控件的简单使用,而是在接触 Qt 比较标准的数据展示思路了。文档里这一节也正是按这条链写的:从 plainTextEdit->document() 取得文档对象,用 blockCount() 和 findBlockByNumber() 逐行提取文本,再用 QStringListModel 绑定到 listView。【turn9file12】
一、这个模块到底在学什么
这次可以拆成 4 层。
1. 输入层
左侧 QPlainTextEdit 负责承载多行文本输入。
它适合:
-
逐行输入
-
大段纯文本
-
日志
-
配置片段
-
代码/列表文本
2. 文本结构层
Qt 并不把多行文本简单当成一个大字符串处理,而是通过 QTextDocument 和 QTextBlock 组织文本。
也就是:
3. 数据容器层
每一行提取后放入:
也就是一个字符串列表。
4. 视图层
最后不是直接把字符串“塞给 listView”,而是:
这说明你已经在学 Qt 的 Model/View 基本思路了。
二、每个模块 / 函数的详细教学
下面按你要求,把这次新增的模块和函数逐个详细讲清楚。
A. QPlainTextEdit 详细教学
A.1 它是什么
QPlainTextEdit 是 Qt 的纯文本多行编辑控件。
它和 QTextEdit 的区别非常重要:
QPlainTextEdit
-
适合纯文本
-
不强调富文本格式
-
更适合代码、日志、配置、逐行文本
QTextEdit
-
支持富文本
-
支持更复杂的格式化内容
-
适合富文本编辑、带样式内容
所以这次文档选 QPlainTextEdit 很合理,因为你的需求是:
逐行输入文本,然后按行处理
这正是 QPlainTextEdit 的典型场景。参考资料里也明确把 QPlainTextEdit 定位为多行纯文本输入控件。
A.2 这次为什么不用 QLineEdit
因为 QLineEdit 只能处理单行文本,而你这次的核心前提是:
所以必须用多行文本控件。
A.3 最核心接口
你这次没有直接用 toPlainText(),而是用了更结构化的方式:
QTextDocument *doc = ui->plainTextEdit->document();
这说明 QPlainTextEdit 的真正强大之处不只是“能输入多行”,而是:
它背后有一个文本文档对象模型
B. QTextDocument 详细教学
B.1 它是什么
QTextDocument 是 Qt 的文档对象,用于表示整个文本内容。
你可以把它理解为:
plainTextEdit背后的“全文数据结构”
这次代码:
QTextDocument *doc = ui->plainTextEdit->document();
就是从控件中取出这个底层文档对象。
B.2 这次为什么要先拿 document()
因为你不是只想拿“整段文本字符串”,而是想按行处理。
而按行处理更适合直接操作文档结构,而不是自己用字符串 split() 硬拆。
所以这里的思想是:
B.3 最核心接口:blockCount()
int count = doc->blockCount();
作用:
获取当前文档里有多少个文本块
在这类纯文本场景里,你基本可以把“文本块”理解成“行”。
所以这句等价于:
当前一共有多少行文本
文档原例就是用 blockCount() 来统计行数。【turn9file12】
C. QTextBlock 详细教学
C.1 它是什么
QTextBlock 是 Qt 文本文档中的文本块对象。
在你的这个案例里,可以近似理解为:
一行文本
C.2 最核心接口:findBlockByNumber()
QTextBlock textLine = doc->findBlockByNumber(x);
作用:
根据行号/块号,取出对应的那一块文本
这一步非常关键,因为它完成了:
C.3 text()
QString str = textLine.text();
作用:
取出该文本块里的纯文本内容
这就实现了从文档逐行提取字符串。
C.4 为什么这比手写字符串分割更有教学价值
你当然可以后面用:
ui->plainTextEdit->toPlainText().split('\n')
来做类似事情。
但文档这次故意用了 QTextDocument + QTextBlock,是为了让你理解:
Qt 的文本编辑控件不是“黑箱字符串框”,而是有结构化文本模型的。
这点很重要。
D. QStringList 详细教学
D.1 它是什么
QStringList 是 Qt 的字符串列表类。
你可以把它理解为:
你这次用它来暂存每一行文本:
QStringList data;
data << str;
D.2 这次为什么它合适
因为你最终想要的是:
-
一行一项
-
多项有顺序
-
可以整体交给列表模型
这正是 QStringList 的典型用途。
D.3 最常见操作
你这次用到的是:
data << str;
这表示把一个字符串追加到列表中。
以后你还会常用:
-
append(...) -
count() -
下标访问
E. QStringListModel 详细教学
这是这次最关键的新模块之一。
E.1 它是什么
QStringListModel 是 Qt 提供的一个字符串列表模型类。
它的作用是:
把一个
QStringList包装成可供视图控件读取的数据模型
也就是:
E.2 这次为什么必须用它
因为 QListView 不是 QListWidget。
QListView 自己不存数据,它只负责“看模型并显示”。
所以你不能直接对 QListView 说“来,显示这几行字符串”,而是要先给它一个模型。
这就是 Qt 的 Model/View 思路。
E.3 最核心构造方式
你写的是:
QStringListModel *model = new QStringListModel(data, this);
含义是:
-
用
data初始化模型 -
把
this作为父对象,便于内存管理
文档里原写法也是创建 QStringListModel 后设置给 listView。【turn9file12】
E.4 为什么我让你加 this
因为如果写成:
QStringListModel *model = new QStringListModel(data);
也能跑,但父对象不明确。
加上 this 后,Qt 对象树会帮你更好管理内存。
F. QListView 详细教学
F.1 它是什么
QListView 是 Qt 的列表视图控件。
它只负责:
把模型中的数据按列表形式显示出来
所以它和 QListWidget 的区别非常关键:
QListWidget
-
自带数据项管理
-
更像“控件里直接塞内容”
-
更适合简单场景
QListView
-
只负责显示
-
数据要来自模型
-
更符合 Qt 的 Model/View 架构
F.2 这次为什么用 QListView
因为文档这一节显然想让你开始接触更标准的 Qt 写法:
而不是停留在“直接加几个列表项”的层面。
F.3 最核心接口:setModel()
ui->listView->setModel(model);
作用:
给视图指定一个数据模型
从这一刻开始,listView 的显示内容就来自 model。
三、状态栏相关内容的详细教学
这次你还顺带首次稳定用到了 QStatusBar。
A. QStatusBar 是什么
QStatusBar 是 Qt 主窗口中的状态栏控件,一般位于窗口底部。
它适合显示:
-
提示信息
-
当前状态
-
临时消息
-
右侧固定信息
B. 这次你怎么用的
QStatusBar *stBar = statusBar();
setStatusBar(stBar);
这里 statusBar() 是 QMainWindow 提供的接口,用来获取主窗口状态栏。
然后你又加了两个标签:
stBar->addWidget(label);
stBar->addPermanentWidget(label2);
表示:
-
左侧普通状态信息
-
右侧永久状态信息
文档原例就是这么写的。【turn9file12】
C. 为什么这次状态栏不是核心,但仍值得认识
因为它说明:
Qt 主窗口不只有“中心区域”,还有菜单栏、工具栏、状态栏等标准区域
这会帮助你后面理解更完整的桌面 GUI 结构。
四、为什么这里用 Model/View,而不是直接往界面塞文本
这是这节最重要的思想点之一。
如果只是为了“把几行字显示出来”,你当然可以想:
-
为什么不用
QListWidget? -
为什么不直接
addItem()?
答案是:
因为这节不是只教你“显示列表”,而是在教你 Qt 更标准的思路:
它的好处是:
-
数据和显示分离
以后数据变了,模型更新即可,视图不必重写逻辑。 -
更容易扩展
同一份数据可以换成别的视图显示。 -
更接近真实项目
很多复杂界面不会把数据直接塞进控件,而是走模型层。
五、本模块新增模块的重点系统总结
下面把这次新出现的东西系统总结一遍。
1. QPlainTextEdit
定义
多行纯文本编辑控件
适合场景
-
代码
-
日志
-
配置
-
多行输入
-
一行一条记录的文本输入
本次作用
左侧多行文本输入源
2. QTextDocument
定义
文本控件背后的文档对象
核心接口
-
blockCount() -
findBlockByNumber(...)
本次作用
把 plainTextEdit 的全文结构化表示出来,便于逐行访问
3. QTextBlock
定义
文本块对象,在本例里可近似看成“一行”
核心接口
text()
本次作用
逐行取出文本内容
4. QStringList
定义
字符串列表类
本次作用
暂存每一行文本
5. QStringListModel
定义
把字符串列表包装成模型的类
本次作用
作为 listView 的数据模型
6. QListView
定义
列表视图控件
核心接口
setModel(...)
本次作用
把模型中的多行文本显示成列表
7. QStatusBar
定义
主窗口状态栏
本次作用
底部显示提示信息和固定信息
六、这个模块最重要的知识点
1. QPlainTextEdit 适合多行纯文本,不是富文本
这和 QTextEdit 要区分清楚。
2. 文本控件背后有文档模型
不是只有一个大字符串,而是可以按块、按行访问。
3. QListView 本身不存数据,它依赖模型
这是你第一次比较明确接触 Qt 的 Model/View 思想。
4. 逐行处理文本时,QTextDocument + QTextBlock 是一种标准思路
这比手写字符串切分更能帮助你理解 Qt 的文本体系。
七、这个模块最容易踩的坑
易错点 1:把 QListView 当成 QListWidget
如果你想直接 addItem(),那是 QListWidget 的思路,不是这次案例的思路。
易错点 2:忘记给 QStringListModel 设父对象
虽然不一定立刻报错,但内存管理会更乱。
易错点 3:误以为 blockCount() 就一定等于“非空行数”
它统计的是文本块数,不一定等于“有内容的行数”。
如果最后有空行,也可能被算进去。
易错点 4:主窗口不是 QMainWindow
那状态栏相关代码就会出问题。
八、你现在应该形成的理解
做完这个模块,你应该明确:
-
QPlainTextEdit是多行纯文本输入控件 -
QTextDocument和QTextBlock提供了结构化文本访问方式 -
QStringList是非常常用的字符串容器 -
QStringListModel + QListView是最基础的 Model/View 组合之一 -
Qt 的很多显示控件并不直接持有数据,而是依赖模型
九、这一模块最值得记住的最小模板
你最值得记住的是这段:
QTextDocument *doc = ui->plainTextEdit->document();
int count = doc->blockCount();
QStringList data;
for (int x = 0; x < count; x++)
{
QTextBlock textLine = doc->findBlockByNumber(x);
QString str = textLine.text();
data << str;
}
QStringListModel *model = new QStringListModel(data, this);
ui->listView->setModel(model);
它代表的是:
这已经是一个非常标准的 Qt 小型数据流模板了。
下一步如果你的 13 个组件还没全部覆盖,我们就继续按这个流程往下推进。你把下一个组件名发我,我继续做阶段 1。