文本编辑器
一、QTextDocument 与框架(Frame)
QTextDocument:QTextEdit的文档对象,存储所有文本与结构。QTextFrame:文档中的“框架容器”,可以包含文本、表格、图片等。- 根框架通过
doc->rootFrame()获取。
示例:设置根框架边框
QTextFrame * root_frame = doc->rootFrame();
QTextFrameFormat format;
format.setBorderBrush(Qt::blue); // 边框颜色
format.setBorder(3); // 边框宽度
root_frame->setFrameFormat(format);
插入子框架
QTextFrameFormat frameFormat;
frameFormat.setBackground(Qt::lightGray);
frameFormat.setMargin(10);
frameFormat.setPadding(5);
frameFormat.setBorder(2);
frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dashed);
QTextCursor cursor = ui->textEdit->textCursor();
cursor.insertFrame(frameFormat);
二、文本块(Block)
QTextBlock:代表文档中的一个段落。- 遍历所有文本块:
QTextBlock block = document->firstBlock();
for(int i = 0; i < document->blockCount(); ++i){
qDebug() << "文本块" << i
<< "首行行号" << block.firstLineNumber()
<< "长度" << block.length()
<< "内容" << block.text();
block = block.next();
}
三、字体与字符格式
- 通过
QTextBlockFormat设置段落属性(对齐方式等)。 - 通过
QTextCharFormat设置文字样式(颜色、字体、下划线等)。
示例:设置字体
QTextCursor cursor = ui->textEdit->textCursor();
// 设置居中段落
QTextBlockFormat blockFormat;
blockFormat.setAlignment(Qt::AlignCenter);
cursor.insertBlock(blockFormat);
// 设置字符样式
QTextCharFormat charFormat;
charFormat.setBackground(Qt::lightGray);
charFormat.setForeground(Qt::blue);
charFormat.setFont(QFont("宋体", 12, QFont::Bold, true));
charFormat.setFontUnderline(true);
cursor.setCharFormat(charFormat);
cursor.insertText("插入字体");
四、表格、列表、图片
1. 插入表格
QTextTableFormat format;
format.setCellSpacing(2); // 单元格间距
format.setCellPadding(10); // 单元格内边距
cursor.insertTable(2, 2, format); // 插入 2x2 表格
2. 插入有序列表
QTextListFormat format;
format.setStyle(QTextListFormat::ListDecimal); // 数字编号
ui->textEdit->textCursor().insertList(format);
3. 插入图片
QTextImageFormat format;
format.setName("C:/Users/lyx/Pictures/shuita.jpg"); // 图片路径
ui->textEdit->textCursor().insertImage(format);
⚠️ 注意::xxx 表示 Qt 资源文件,C:/xxx 才是本地路径。
五、查找功能
- 创建查找对话框:
findDialog = new QDialog(this);
lineEdit = new QLineEdit(findDialog);
QPushButton * btn = new QPushButton("查找下一个", findDialog);
connect(btn, &QPushButton::clicked, this, &MainWindow::findNext);
QVBoxLayout * layout = new QVBoxLayout();
layout->addWidget(lineEdit);
layout->addWidget(btn);
findDialog->setLayout(layout);
- 查找文本:
QString string = lineEdit->text();
bool isFind = ui->textEdit->find(string, QTextDocument::FindBackward);
if(isFind) {
qDebug() << "行号:" << ui->textEdit->textCursor().blockNumber()
<< "列号:" << ui->textEdit->textCursor().columnNumber();
}
六、工具栏动作(QAction)
通过 QAction 把功能按钮添加到 QToolBar:
QAction * action_textBlock = new QAction("文本块", this);
connect(action_textBlock, &QAction::triggered, this, &MainWindow::showTextBlock);
ui->toolBar->addAction(action_textBlock);
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextDocument>
#include <QTextFrame>
#include <QTextFrameFormat>
#include <QTextBlockFormat>
#include <QTextCursor>
#include <QAction>
#include <QDebug>
#include <QTextCharFormat>
#include <QTextTableFormat>
#include <QTextImageFormat>
#include <QTextListFormat>
#include <QPushButton>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this); // 初始化 UI 界面
// 获取 QTextEdit 的文档对象
QTextDocument * doc = ui->textEdit->document();
QTextFrame * root_frame = doc->rootFrame(); // 文档的根框架
// 设置根框架的边框样式
QTextFrameFormat format;
format.setBorderBrush(Qt::blue); // 边框颜色
format.setBorder(3); // 边框宽度
root_frame->setFrameFormat(format);
// 创建一个子框架的格式
QTextFrameFormat frameFormat;
frameFormat.setBackground(Qt::lightGray); // 背景色
frameFormat.setMargin(10); // 外边距
frameFormat.setPadding(5); // 内边距
frameFormat.setBorder(2); // 边框宽度
frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dashed); // 虚线边框
// 在光标位置插入新框架
QTextCursor cursor = ui->textEdit->textCursor();
cursor.insertFrame(frameFormat);
// 向框架中插入文字
ui->textEdit->insertPlainText("inner text!\n");
ui->textEdit->insertPlainText("Hello inner text !\n");
// 工具栏动作:显示框架结构
QAction * action_frame = new QAction("Frame", this);
connect(action_frame, &QAction::triggered, this, &MainWindow::showTextFrame);
ui->toolBar->addAction(action_frame);
// 工具栏动作:显示文档的文本块
QAction * action_textBlock = new QAction(tr("文本块"), this);
connect(action_textBlock, &QAction::triggered, this, &MainWindow::showTextBlock);
ui->toolBar->addAction(action_textBlock);
// 工具栏动作:设置字体(可切换)
QAction * action_font = new QAction(tr("字体"), this);
action_font->setCheckable(true); // 允许勾选
connect(action_font, &QAction::toggled, this, &MainWindow::setTextFont);
ui->toolBar->addAction(action_font);
// 工具栏动作:插入表格
QAction * action_textTable = new QAction(tr("表格"), this);
connect(action_textTable, &QAction::triggered, this, &MainWindow::insertTable);
ui->toolBar->addAction(action_textTable);
// 工具栏动作:插入列表
QAction * action_textList = new QAction(tr("列表"), this);
connect(action_textList, &QAction::triggered, this, &MainWindow::insertList);
ui->toolBar->addAction(action_textList);
// 工具栏动作:插入图片
QAction * action_textImage = new QAction(tr("图片"), this);
connect(action_textImage, &QAction::triggered, this, &MainWindow::insertImage);
ui->toolBar->addAction(action_textImage);
// 工具栏动作:查找功能
QAction * action_textFind = new QAction(tr("查找"), this);
connect(action_textFind, &QAction::triggered, this, &MainWindow::textFind);
ui->toolBar->addAction(action_textFind);
// 查找对话框
findDialog = new QDialog(this);
lineEdit = new QLineEdit(findDialog); // 输入查找内容的行编辑框
QPushButton * btn = new QPushButton(findDialog);
btn->setText(tr("查找下一个"));
connect(btn, &QPushButton::clicked, this, &MainWindow::findNext);
// 设置查找对话框布局
QVBoxLayout * layout = new QVBoxLayout();
layout->addWidget(lineEdit);
layout->addWidget(btn);
findDialog->setLayout(layout);
}
MainWindow::~MainWindow()
{
delete ui; // 释放 UI
}
// 遍历根框架,输出其中的子框架和文本块
void MainWindow::showTextFrame()
{
auto doc = ui->textEdit->document();
auto rootFrame = doc->rootFrame();
for(auto iter = rootFrame->begin(); iter != rootFrame->end(); iter++){
auto cur_frame = iter.currentFrame(); // 当前是否是 frame
auto cur_block = iter.currentBlock(); // 当前是否是 block
if(cur_frame){
qDebug() << "cur node is frame"; // 节点是框架
} else if (cur_block.isValid()){
qDebug() << "cur node is text block, text is " << cur_block.text(); // 节点是文本块
}
}
}
// 遍历所有文本块,输出内容与属性
void MainWindow::showTextBlock()
{
QTextDocument * document = ui->textEdit->document();
QTextBlock block = document->firstBlock();
for(int i = 0; i < document->blockCount(); ++i){
qDebug() << tr("文本块%1, 文本块首行行号%2, 长度%3, 内容%4 ")
.arg(i) // 文本块编号
.arg(block.firstLineNumber()) // 首行行号
.arg(block.length()) // 文本块长度
.arg(block.text()); // 文本内容
block = block.next();
}
}
// 设置字体样式
void MainWindow::setTextFont(bool checked)
{
QTextCursor cursor = ui->textEdit->textCursor();
if(checked){
// 插入居中文本块
QTextBlockFormat blockFormat;
blockFormat.setAlignment(Qt::AlignCenter);
cursor.insertBlock(blockFormat);
// 设置字符格式
QTextCharFormat charFormat;
charFormat.setBackground(Qt::lightGray); // 背景色
charFormat.setForeground(Qt::blue); // 前景色
charFormat.setFont(QFont(tr("宋体"), 12, QFont::Bold, true)); // 字体设置:宋体 12号 粗体 斜体
charFormat.setFontUnderline(true); // 下划线
cursor.setCharFormat(charFormat);
cursor.insertText(tr("插入字体")); // 插入文字
} else {
// 恢复左对齐、默认字体
QTextBlockFormat blockFormat;
blockFormat.setAlignment(Qt::AlignLeft);
cursor.insertBlock(blockFormat);
QTextCharFormat charFormat;
cursor.setCharFormat(charFormat);
cursor.insertText(tr("微软雅黑"));
}
}
// 插入表格
void MainWindow::insertTable()
{
QTextCursor cursor = ui->textEdit->textCursor();
QTextTableFormat format;
format.setCellSpacing(2); // 单元格间距
format.setCellPadding(10); // 单元格内边距
cursor.insertTable(2, 2, format); // 插入 2x2 表格
}
// 插入图片
void MainWindow::insertImage()
{
QTextImageFormat format;
// 注意:这里路径写法有误,:/ 开头是资源文件,C:/ 开头是本地路径
format.setName(":/C:/Users/lyx/Pictures/shuita.jpg");
ui->textEdit->textCursor().insertImage(format);
}
// 插入有序列表
void MainWindow::insertList()
{
QTextListFormat format;
format.setStyle(QTextListFormat::ListDecimal); // 数字编号列表
ui->textEdit->textCursor().insertList(format);
}
// 显示查找对话框
void MainWindow::textFind()
{
findDialog->show();
}
// 查找下一个匹配项
void MainWindow::findNext()
{
QString string = lineEdit->text();
// 向后查找
bool isFind = ui->textEdit->find(string, QTextDocument::FindBackward);
if(isFind) {
qDebug() << tr("行号:%1 列号:%2")
.arg(ui->textEdit->textCursor().blockNumber()) // 当前光标行号
.arg(ui->textEdit->textCursor().columnNumber()); // 当前光标列号
}
}

浙公网安备 33010602011771号